HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Calculate working minutes between two timestamps

Submitted by: @import:stackexchange-codereview··
0
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

Solution

A few points:

Avoid magic numbers

The number 480 (number of minutes in a working day) appears repeatedly. Promote it to a CONSTANT.

Superflous else

The following code can be shortened:

if cond:
    return
else:
    pass


to:

if cond:
    return
pass


Tuple 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 = starttime


is 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_mins

Code Snippets

if cond:
    return
else:
    pass
if cond:
    return
pass
starttime, endtime = (datetime.datetime.fromtimestamp(int(t)/1000) for t in (start, end))
if starttime < startday:
    periodstart = startday
else:
    periodstart = starttime
periodstart = max(starttime, startday)

Context

StackExchange Code Review Q#135142, answer score: 2

Revisions (0)

No revisions yet.