By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,272 Members | 1,408 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,272 IT Pros & Developers. It's quick & easy.

Finding specific date ranges

P: n/a
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 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
ky******@gmail.com 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
Sep 6 '07 #2

P: n/a
On Sep 6, 10:57 am, Tim Golden <m...@timgolden.me.ukwrote:
kyoso...@gmail.com 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 '07 #3

P: n/a
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
Sep 6 '07 #4

P: n/a
On Sep 6, 12:41 pm, Tim Golden <t...@timgolden.me.ukwrote:
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 '07 #5

P: n/a
ky******@gmail.com wrote:
On Sep 6, 12:41 pm, Tim Golden <t...@timgolden.me.ukwrote:
>>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
Sep 6 '07 #6

P: n/a
On Sep 6, 2:39 pm, Tim Golden <t...@timgolden.me.ukwrote:
>
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 '07 #7

P: n/a
On Sep 6, 7:56 am, kyoso...@gmail.com 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.

Sep 6 '07 #8

P: n/a
Zentrader wrote:
On Sep 6, 7:56 am, kyoso...@gmail.com 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
Sep 7 '07 #9

P: n/a
On Sep 6, 6:41 pm, Zentrader <zentrad...@gmail.comwrote:
On Sep 6, 7:56 am, kyoso...@gmail.com 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 '07 #10

P: n/a
Tim Golden wrote:
ky******@gmail.com 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

Sep 7 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.