patternpythonMinor
Calculate working minutes between two timestamps
Viewed 0 times
workingtwobetweencalculateminutestimestamps
Problem
I've created a function to calculate the working minutes between two timestamps.
I class working minutes as those between 9am - 5pm and not on weekends or national holidays.
The holidays are those in the UK.
I think the function itself is quite quick, although generating the initial series probably takes a bit of time.
Because the working dates are fixed, I might just put them into a database table and load them each time the function is called, probably a bit faster.
```
import pandas as pd
import datetime
from pandas.tseries.holiday import Holiday, AbstractHolidayCalendar
from pandas.tseries.offsets import CDay
class HolidayCalendar(AbstractHolidayCalendar):
rules =[Holiday('Xmas Day generic',month=12,day=25),
Holiday('NYD generic',month=1,day=1),
Holiday('Boxing Day generic',month=12,day=26),
Holiday('Good Friday 2015',year=2015,month=4,day=3),
Holiday('Easter Monday 2015',year=2015,month=4,day=6),
Holiday('May Bank Holiday 2015',year=2015,month=5,day=4),
Holiday('Spring Bank Holiday 2015',year=2015,month=5,day=25),
Holiday('Summer Bank Holiday 2015',year=2015,month=8,day=31),
Holiday('Boxing Day 2015',year=2015,month=12,day=28),
Holiday('Good Friday 2016',year=2016,month=3,day=25),
Holiday('Easter Monday 2016',year=2016,month=3,day=28),
Holiday('May Bank 2016',year=2016,month=5,day=2),
Holiday('Spring Bank 2016',year=2016,month=5,day=30),
Holiday('Summer Bank 2016',year=2016,month=8,day=29),
Holiday('Boxing Day 2016',year=2016,month=12,day=26),
Holiday('Xmas Day 2016',year=2016,month=12,day=27),
Holiday('NYD 2017',year=2017,month=1,day=2),
Holiday('Good Friday 2017',year=2017,month=4,day=14),
Holiday('Easter Monday 2017',year=2017,month=4,day=17),
Holiday('May Bank 2017',year=2017,month=5,day=1),
Holiday('Spring B
I class working minutes as those between 9am - 5pm and not on weekends or national holidays.
The holidays are those in the UK.
I think the function itself is quite quick, although generating the initial series probably takes a bit of time.
Because the working dates are fixed, I might just put them into a database table and load them each time the function is called, probably a bit faster.
```
import pandas as pd
import datetime
from pandas.tseries.holiday import Holiday, AbstractHolidayCalendar
from pandas.tseries.offsets import CDay
class HolidayCalendar(AbstractHolidayCalendar):
rules =[Holiday('Xmas Day generic',month=12,day=25),
Holiday('NYD generic',month=1,day=1),
Holiday('Boxing Day generic',month=12,day=26),
Holiday('Good Friday 2015',year=2015,month=4,day=3),
Holiday('Easter Monday 2015',year=2015,month=4,day=6),
Holiday('May Bank Holiday 2015',year=2015,month=5,day=4),
Holiday('Spring Bank Holiday 2015',year=2015,month=5,day=25),
Holiday('Summer Bank Holiday 2015',year=2015,month=8,day=31),
Holiday('Boxing Day 2015',year=2015,month=12,day=28),
Holiday('Good Friday 2016',year=2016,month=3,day=25),
Holiday('Easter Monday 2016',year=2016,month=3,day=28),
Holiday('May Bank 2016',year=2016,month=5,day=2),
Holiday('Spring Bank 2016',year=2016,month=5,day=30),
Holiday('Summer Bank 2016',year=2016,month=8,day=29),
Holiday('Boxing Day 2016',year=2016,month=12,day=26),
Holiday('Xmas Day 2016',year=2016,month=12,day=27),
Holiday('NYD 2017',year=2017,month=1,day=2),
Holiday('Good Friday 2017',year=2017,month=4,day=14),
Holiday('Easter Monday 2017',year=2017,month=4,day=17),
Holiday('May Bank 2017',year=2017,month=5,day=1),
Holiday('Spring B
Solution
A few points:
Avoid magic numbers
The number 480 (number of minutes in a working day) appears repeatedly. Promote it to a
Superflous
The following code can be shortened:
to:
Tuple assignment
You can use tuple assignment to get rid of some redundancy:
Reduce logic
Your comparing logic can be greatly reduce.
First, note that:
is equivalent to:
Also the case for 1, 2 and more than 2 days are very similar. For the secon
Also
With these few changes I arrive at (omitting the setup code for the holidays for brevity):
Avoid magic numbers
The number 480 (number of minutes in a working day) appears repeatedly. Promote it to a
CONSTANT.Superflous
elseThe following code can be shortened:
if cond:
return
else:
passto:
if cond:
return
passTuple assignment
You can use tuple assignment to get rid of some redundancy:
starttime, endtime = (datetime.datetime.fromtimestamp(int(t)/1000) for t in (start, end))Reduce logic
Your comparing logic can be greatly reduce.
First, note that:
if starttime < startday:
periodstart = startday
else:
periodstart = starttimeis equivalent to:
periodstart = max(starttime, startday)Also the case for 1, 2 and more than 2 days are very similar. For the secon
(daycount-2)*480 is just zero, for the first it is -1.Also
if daycount == 0 might be better written as if not days, since an empty list evaluates as false. This allows us to get rid of the variable daycount, since it is only needed once now.With these few changes I arrive at (omitting the setup code for the holidays for brevity):
FULL_WORKDAY = 480 # min
def count_mins(start, end):
starttime, endtime = (datetime.datetime.fromtimestamp(int(t)/1000) for t in (start, end))
days = day_series[starttime.date():endtime.date()]
if not days:
return 0
first_day_mins = min(FULL_WORKDAY, (days[0].replace(hour9, minute=0, second=0) - starttime).seconds/60)
last_day_mins = min(FULL_WORKDAY, (endtime - days[-1].replace(hour=17, minute=0, second=0)).seconds/60)
return first_day_mins + (len(days)-2)*FULL_WORKDAY + last_day_minsCode Snippets
if cond:
return
else:
passif cond:
return
passstarttime, endtime = (datetime.datetime.fromtimestamp(int(t)/1000) for t in (start, end))if starttime < startday:
periodstart = startday
else:
periodstart = starttimeperiodstart = max(starttime, startday)Context
StackExchange Code Review Q#135142, answer score: 2
Revisions (0)
No revisions yet.