Finding specific date ranges

Discussion in 'Python' started by kyosohma@gmail.com, Sep 6, 2007.

  1. Guest

    Hi,

    I am working on a timesheet application in which I need to to find the
    first pay period in a month that is entirely contained in that month
    to calculate vacation time. Below are some example date ranges:


    December 31, 2006 January 13, 2007 # doesn't earn
    January 14, 2007 January 27, 2007 # does earn
    January 28, 2007 February 10, 2007 # doesn't
    February 11, 2007 February 24, 2007 # does


    So far, the best approach I've come up with is to create a list of
    tuples that contain the pay period date ranges for the year and
    iterate through the tuples looking for the first occurrence of the
    month names matching. Then I'd add that date range to a separate list
    and somehow ignore any other matches in that month. This seems like a
    hack. Does anyone have a better idea?

    Thanks in advance!

    Mike
    , Sep 6, 2007
    #1
    1. Advertising

  2. Tim Golden Guest

    wrote:
    > Hi,
    >
    > I am working on a timesheet application in which I need to to find the
    > first pay period in a month that is entirely contained in that month
    > to calculate vacation time. Below are some example date ranges:
    >
    >
    > December 31, 2006 January 13, 2007 # doesn't earn
    > January 14, 2007 January 27, 2007 # does earn
    > January 28, 2007 February 10, 2007 # doesn't
    > February 11, 2007 February 24, 2007 # does
    >
    >
    > So far, the best approach I've come up with is to create a list of
    > tuples that contain the pay period date ranges for the year and
    > iterate through the tuples looking for the first occurrence of the
    > month names matching. Then I'd add that date range to a separate list
    > and somehow ignore any other matches in that month. This seems like a
    > hack. Does anyone have a better idea?



    Well, I can come up with a solution which basically reflects the
    way I'd do it in SQL (since this kind of thing is my bread-and-butter
    there) but I'm not convinced it's really any better than your proposal.
    However, for the purposes of illustration:

    <code>
    import calendar
    import datetime

    YEAR = 2007

    months = [
    (datetime.date (YEAR, n, 1), datetime.date (YEAR, n, calendar.monthrange (YEAR, n)[1]))
    for n in range (1, 13)
    ]

    periods = [
    (datetime.date(2006, 12, 31), datetime.date(2007, 1, 13)),
    (datetime.date(2007, 1, 14), datetime.date(2007, 1, 27)),
    (datetime.date(2007, 1, 28), datetime.date(2007, 2, 10)),
    (datetime.date(2007, 2, 11), datetime.date(2007, 2, 24))
    ]

    for m in months:
    candidate_periods = [p for p in periods if m[0] <= p[0] and p[1] <= m[1]]
    if candidate_periods:
    print m[0], "=>", min (candidate_periods)
    else:
    print m[0], "=>", "no period matches"

    </code>

    TJG
    Tim Golden, Sep 6, 2007
    #2
    1. Advertising

  3. Guest

    On Sep 6, 10:57 am, Tim Golden <> wrote:
    > wrote:
    > > Hi,

    >
    > > I am working on a timesheet application in which I need to to find the
    > > first pay period in a month that is entirely contained in that month
    > > to calculate vacation time. Below are some example date ranges:

    >
    > > December 31, 2006 January 13, 2007 # doesn't earn
    > > January 14, 2007 January 27, 2007 # does earn
    > > January 28, 2007 February 10, 2007 # doesn't
    > > February 11, 2007 February 24, 2007 # does

    >
    > > So far, the best approach I've come up with is to create a list of
    > > tuples that contain the pay period date ranges for the year and
    > > iterate through the tuples looking for the first occurrence of the
    > > month names matching. Then I'd add that date range to a separate list
    > > and somehow ignore any other matches in that month. This seems like a
    > > hack. Does anyone have a better idea?

    >
    > Well, I can come up with a solution which basically reflects the
    > way I'd do it in SQL (since this kind of thing is my bread-and-butter
    > there) but I'm not convinced it's really any better than your proposal.
    > However, for the purposes of illustration:
    >
    > <code>
    > import calendar
    > import datetime
    >
    > YEAR = 2007
    >
    > months = [
    > (datetime.date (YEAR, n, 1), datetime.date (YEAR, n, calendar.monthrange (YEAR, n)[1]))
    > for n in range (1, 13)
    > ]
    >
    > periods = [
    > (datetime.date(2006, 12, 31), datetime.date(2007, 1, 13)),
    > (datetime.date(2007, 1, 14), datetime.date(2007, 1, 27)),
    > (datetime.date(2007, 1, 28), datetime.date(2007, 2, 10)),
    > (datetime.date(2007, 2, 11), datetime.date(2007, 2, 24))
    > ]
    >
    > for m in months:
    > candidate_periods = [p for p in periods if m[0] <= p[0] and p[1] <= m[1]]
    > if candidate_periods:
    > print m[0], "=>", min (candidate_periods)
    > else:
    > print m[0], "=>", "no period matches"
    >
    > </code>
    >
    > TJG


    Thanks! I'll try it both ways and see if there's any appreciable
    difference in speed, although since it will be packaged into an
    executable, that may not be an issue anyway.

    Mike
    , Sep 6, 2007
    #3
  4. Tim Golden Guest

    > Thanks! I'll try it both ways and see if there's any appreciable
    > difference in speed, although since it will be packaged into an
    > executable, that may not be an issue anyway.
    >
    > Mike


    I honestly doubt there's any advantage to my approach, certainly
    not in terms of speed. It's really only if it happens to suit
    your mind better, or take advantage of structures you might
    already have in place, etc.

    TJG
    Tim Golden, Sep 6, 2007
    #4
  5. Guest

    On Sep 6, 12:41 pm, Tim Golden <> wrote:
    > > Thanks! I'll try it both ways and see if there's any appreciable
    > > difference in speed, although since it will be packaged into an
    > > executable, that may not be an issue anyway.

    >
    > > Mike

    >
    > I honestly doubt there's any advantage to my approach, certainly
    > not in terms of speed. It's really only if it happens to suit
    > your mind better, or take advantage of structures you might
    > already have in place, etc.
    >
    > TJG


    For completeness, here's my method for comparison's sake:

    <code>

    date_list = [('12/31/2006', '01/13/2007'),
    ('01/14/2007', '01/27/2007'),
    ('01/28/2007', '02/10/2007'),
    ('02/11/2007', '02/24/2007'),
    ('02/25/2007', '03/10/2007'),
    ('03/11/2007', '03/24/2007'),
    ('03/25/2007', '04/07/2007'),
    ('04/08/2007', '04/21/2007'),
    ('04/22/2007', '05/05/2007'),
    ('05/06/2007', '05/19/2007'),
    ('05/20/2007', '06/02/2007'),
    ('06/03/2007', '06/16/2007'),
    ('06/17/2007', '06/30/2007')
    ]
    vac_periods = []
    found = False
    for d in date_list:
    begin = d[0][0:2]
    end = d[1][0:2]
    if begin == end and found == False:
    vac_periods.append(d)
    found = True
    else:
    found = False
    print vac_periods

    </code>

    Isn't it kind of late in the day over there, Tim? Anyway, your method
    is probably clearer to read whereas mine doesn't require anything to
    be imported. I didn't even realize there was a calendar module...or
    maybe I forgot about it.

    Mike
    , Sep 6, 2007
    #5
  6. Tim Golden Guest

    wrote:
    > On Sep 6, 12:41 pm, Tim Golden <> wrote:
    >>> Thanks! I'll try it both ways and see if there's any appreciable
    >>> difference in speed, although since it will be packaged into an
    >>> executable, that may not be an issue anyway.
    >>> Mike

    >> I honestly doubt there's any advantage to my approach, certainly
    >> not in terms of speed. It's really only if it happens to suit
    >> your mind better, or take advantage of structures you might
    >> already have in place, etc.
    >>
    >> TJG

    >
    > For completeness, here's my method for comparison's sake:
    >

    [... snipped ...]

    > Isn't it kind of late in the day over there, Tim?


    (It's about 8.30pm as I write this, so still awake :)

    > Anyway, your method is probably clearer to read whereas mine
    > doesn't require anything to be imported.


    I think I've been a SQL & Python programmer for so long that
    I tend to do anything -- and sometimes too much -- to avoid
    messy loop/exit-when structures. On reflection, my code
    would be simplified by ignoring all the datetime.date stuff
    which is irrelevant for the purpose, since tuples will
    compare perfectly well. Also, I had to put the conditional
    in the loop because I didn't have data for every month. If
    you *knew* you had at least one period for each month and
    weren't fussed about, say, date arithmetic later on, it
    would be even simpler, just a min () function around
    a generator expression.

    Frankly, though, with code as small scale as this, it's
    far more important what *you* the programmer and any
    future maintainers will find easy to understand and use,
    and far less important how clever the code is or how
    fast it runs.

    > I didn't even realize there was a calendar module...or
    > maybe I forgot about it.


    Even now, after some seven years of using Python, I'm
    *still* surprised when I read someone's blog article or
    mailing list posting referring to a module or application
    I never knew about, or had completely forgotten.

    TJG
    Tim Golden, Sep 6, 2007
    #6
  7. Guest

    On Sep 6, 2:39 pm, Tim Golden <> wrote:
    >
    > > Anyway, your method is probably clearer to read whereas mine

    >
    > > doesn't require anything to be imported.

    >
    > I think I've been a SQL & Python programmer for so long that
    > I tend to do anything -- and sometimes too much -- to avoid
    > messy loop/exit-when structures. On reflection, my code
    > would be simplified by ignoring all the datetime.date stuff
    > which is irrelevant for the purpose, since tuples will
    > compare perfectly well. Also, I had to put the conditional
    > in the loop because I didn't have data for every month. If
    > you *knew* you had at least one period for each month and
    > weren't fussed about, say, date arithmetic later on, it
    > would be even simpler, just a min () function around
    > a generator expression.
    >



    I'm getting pretty sick of for loops, flags and/or sentinel values. I
    do *know* that there should be one (and only one) period per month
    that applies. I just have to grab that period. I currently calculate
    the date ranges on the fly based on the last date in the 2-value pair.
    Ugh.

    I've read an re-read about generators, but they seem to cause my mind
    to go blank. It's like the related with statement or decorators. I
    just don't understand them well enough to implement them.


    > Frankly, though, with code as small scale as this, it's
    > far more important what *you* the programmer and any
    > future maintainers will find easy to understand and use,
    > and far less important how clever the code is or how
    > fast it runs.


    I agree. The simpler the code is to read and maintain, the better.
    Clever, short code may be cool, but it can also be a pain to
    troubleshoot.

    Mike
    , Sep 6, 2007
    #7
  8. Zentrader Guest

    On Sep 6, 7:56 am, wrote:
    > December 31, 2006 January 13, 2007 # doesn't earn
    > January 14, 2007 January 27, 2007 # does earn
    > January 28, 2007 February 10, 2007 # doesn't
    > February 11, 2007 February 24, 2007 # does


    Am I over simplifying if I say that since it appears to be a two week
    pay period, the date has to be greater than the 11th unless the first,
    or first and second, are on a weekend, in which case it would be > 12
    or > 13? Or a reasonable facsimile thereof, depending on whether or
    not the two week period is Saturday through Friday.
    Zentrader, Sep 7, 2007
    #8
  9. Tim Golden Guest

    Zentrader wrote:
    > On Sep 6, 7:56 am, wrote:
    >> December 31, 2006 January 13, 2007 # doesn't earn
    >> January 14, 2007 January 27, 2007 # does earn
    >> January 28, 2007 February 10, 2007 # doesn't
    >> February 11, 2007 February 24, 2007 # does

    >
    > Am I over simplifying if I say that since it appears to be a two week
    > pay period, the date has to be greater than the 11th unless the first,
    > or first and second, are on a weekend, in which case it would be > 12
    > or > 13? Or a reasonable facsimile thereof, depending on whether or
    > not the two week period is Saturday through Friday.


    I think it's one of those things where the neatest answer
    could well depend on the sort of heuristic you mention. As
    a rule, when I come across this kind of requirement, I tend
    to put the most general solution in place, unless a *real*
    optimisation is clearly called for. In my experience, this
    makes it much easier for the next person who looks at the
    code, typically years later, even if that's me!

    (This is has just happened to me this week, having to review
    a date-related calculation to do the repost frequency of the
    adverts my company deals with. I wrote the original code five
    years ago, and commented it intelligently, but I *still* had
    to work through the code twice when we had a problem with a
    particular cycle!)

    TJG
    Tim Golden, Sep 7, 2007
    #9
  10. Guest

    On Sep 6, 6:41 pm, Zentrader <> wrote:
    > On Sep 6, 7:56 am, wrote:
    >
    > > December 31, 2006 January 13, 2007 # doesn't earn
    > > January 14, 2007 January 27, 2007 # does earn
    > > January 28, 2007 February 10, 2007 # doesn't
    > > February 11, 2007 February 24, 2007 # does

    >
    > Am I over simplifying if I say that since it appears to be a two week
    > pay period, the date has to be greater than the 11th unless the first,
    > or first and second, are on a weekend, in which case it would be > 12
    > or > 13? Or a reasonable facsimile thereof, depending on whether or
    > not the two week period is Saturday through Friday.


    Yeah it is a 2-week period, but the starting day can change depending
    on whether or not you're salaried. I haven't even looked at how we
    handle unions. Ugh. But yes, you are correct.

    Mike
    , Sep 7, 2007
    #10
  11. Guest

    On Sep 7, 2:47 am, Tim Golden <> wrote:
    > Zentrader wrote:
    > > On Sep 6, 7:56 am, wrote:
    > >> December 31, 2006 January 13, 2007 # doesn't earn
    > >> January 14, 2007 January 27, 2007 # does earn
    > >> January 28, 2007 February 10, 2007 # doesn't
    > >> February 11, 2007 February 24, 2007 # does

    >
    > > Am I over simplifying if I say that since it appears to be a two week
    > > pay period, the date has to be greater than the 11th unless the first,
    > > or first and second, are on a weekend, in which case it would be > 12
    > > or > 13? Or a reasonable facsimile thereof, depending on whether or
    > > not the two week period is Saturday through Friday.

    >
    > I think it's one of those things where the neatest answer
    > could well depend on the sort of heuristic you mention. As
    > a rule, when I come across this kind of requirement, I tend
    > to put the most general solution in place, unless a *real*
    > optimisation is clearly called for. In my experience, this
    > makes it much easier for the next person who looks at the
    > code, typically years later, even if that's me!
    >
    > (This is has just happened to me this week, having to review
    > a date-related calculation to do the repost frequency of the
    > adverts my company deals with. I wrote the original code five
    > years ago, and commented it intelligently, but I *still* had
    > to work through the code twice when we had a problem with a
    > particular cycle!)
    >
    > TJG


    I think it's foolish NOT to comment code unless it's very well self-
    documented. Even then, a couple lines of comments can be helpful. I've
    had to translate a bunch of Kixtart code into Python and none of it
    was commented and it wasn't well formed code either.

    And I've had the same thing happen with code that's only a year old.
    I'll read it and then go "what the?!" It's just not possible to
    remember every line of code you write. I wish it was.

    Mike
    , Sep 7, 2007
    #11
  12. Tim Golden wrote:
    > wrote:
    >> Hi,
    >>
    >> I am working on a timesheet application in which I need to to find the
    >> first pay period in a month that is entirely contained in that month
    >> to calculate vacation time. Below are some example date ranges:
    >>
    >>
    >> December 31, 2006 January 13, 2007 # doesn't earn
    >> January 14, 2007 January 27, 2007 # does earn
    >> January 28, 2007 February 10, 2007 # doesn't
    >> February 11, 2007 February 24, 2007 # does
    >>


    What about (untested) :
    import datetime

    def itEarns(fromDate, toDate) :
    return (fromDate.year == toDate.year and fromDate.month == toDate.month)

    periods = [
    (datetime.date(2006, 12, 31), datetime.date(2007, 1, 13)),
    (datetime.date(2007, 1, 14), datetime.date(2007, 1, 27)),
    (datetime.date(2007, 1, 28), datetime.date(2007, 2, 10)),
    (datetime.date(2007, 2, 11), datetime.date(2007, 2, 24))
    ]

    candidatePeriods = [(frm, to) for frm, to in periods if itEarns(frm, to)]

    ??

    >>
    >> So far, the best approach I've come up with is to create a list of
    >> tuples that contain the pay period date ranges for the year and
    >> iterate through the tuples looking for the first occurrence of the
    >> month names matching. Then I'd add that date range to a separate list
    >> and somehow ignore any other matches in that month. This seems like a
    >> hack. Does anyone have a better idea?

    >
    >
    > Well, I can come up with a solution which basically reflects the
    > way I'd do it in SQL (since this kind of thing is my bread-and-butter
    > there) but I'm not convinced it's really any better than your proposal.
    > However, for the purposes of illustration:
    >
    > <code>
    > import calendar
    > import datetime
    >
    > YEAR = 2007
    >
    > months = [
    > (datetime.date (YEAR, n, 1), datetime.date (YEAR, n, calendar.monthrange (YEAR, n)[1]))
    > for n in range (1, 13)
    > ]
    >
    > periods = [
    > (datetime.date(2006, 12, 31), datetime.date(2007, 1, 13)),
    > (datetime.date(2007, 1, 14), datetime.date(2007, 1, 27)),
    > (datetime.date(2007, 1, 28), datetime.date(2007, 2, 10)),
    > (datetime.date(2007, 2, 11), datetime.date(2007, 2, 24))
    > ]
    >
    > for m in months:
    > candidate_periods = [p for p in periods if m[0] <= p[0] and p[1] <= m[1]]
    > if candidate_periods:
    > print m[0], "=>", min (candidate_periods)
    > else:
    > print m[0], "=>", "no period matches"
    >
    > </code>
    >
    > TJG
    =?ISO-8859-1?Q?Ricardo_Ar=E1oz?=, Sep 7, 2007
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. C
    Replies:
    1
    Views:
    444
    Sunil TG [MVP]
    Oct 29, 2003
  2. Philip Townsend

    Determining date ranges

    Philip Townsend, Nov 6, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    323
    Philip Townsend
    Nov 6, 2003
  3. Peter Grison

    Date, date date date....

    Peter Grison, May 28, 2004, in forum: Java
    Replies:
    10
    Views:
    3,244
    Michael Borgwardt
    May 30, 2004
  4. mazdotnet
    Replies:
    2
    Views:
    394
    Alexey Smirnov
    Oct 2, 2009
  5. Newb Newb

    how to iterate on date ranges

    Newb Newb, Jan 28, 2009, in forum: Ruby
    Replies:
    2
    Views:
    136
    Rob Biedenharn
    Jan 28, 2009
Loading...

Share This Page