Skip to content

Instantly share code, notes, and snippets.

@berglh
Created August 24, 2021 03:50
Show Gist options
  • Save berglh/c44d71f1ea8983ed3e60ce5ef6667eb6 to your computer and use it in GitHub Desktop.
Save berglh/c44d71f1ea8983ed3e60ce5ef6667eb6 to your computer and use it in GitHub Desktop.
Work from Home Calculator
Discover all Working Days in Mon-Fri Pattern
Number of working days for set: 261, numpy: 261 should match
Set working days: ['2020-07-01', '2020-07-02', '2020-07-03', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09', '2020-07-10', '2020-07-13', '2020-07-14', '2020-07-15', '2020-07-16', '2020-07-17', '2020-07-20', '2020-07-21', '2020-07-22', '2020-07-23', '2020-07-24', '2020-07-27', '2020-07-28', '2020-07-29', '2020-07-30', '2020-07-31', '2020-08-03', '2020-08-04', '2020-08-05', '2020-08-06', '2020-08-07', '2020-08-10', '2020-08-11', '2020-08-12', '2020-08-13', '2020-08-14', '2020-08-17', '2020-08-18', '2020-08-19', '2020-08-20', '2020-08-21', '2020-08-24', '2020-08-25', '2020-08-26', '2020-08-27', '2020-08-28', '2020-08-31', '2020-09-01', '2020-09-02', '2020-09-03', '2020-09-04', '2020-09-07', '2020-09-08', '2020-09-09', '2020-09-10', '2020-09-11', '2020-09-14', '2020-09-15', '2020-09-16', '2020-09-17', '2020-09-18', '2020-09-21', '2020-09-22', '2020-09-23', '2020-09-24', '2020-09-25', '2020-09-28', '2020-09-29', '2020-09-30', '2020-10-01', '2020-10-02', '2020-10-05', '2020-10-06', '2020-10-07', '2020-10-08', '2020-10-09', '2020-10-12', '2020-10-13', '2020-10-14', '2020-10-15', '2020-10-16', '2020-10-19', '2020-10-20', '2020-10-21', '2020-10-22', '2020-10-23', '2020-10-26', '2020-10-27', '2020-10-28', '2020-10-29', '2020-10-30', '2020-11-02', '2020-11-03', '2020-11-04', '2020-11-05', '2020-11-06', '2020-11-09', '2020-11-10', '2020-11-11', '2020-11-12', '2020-11-13', '2020-11-16', '2020-11-17', '2020-11-18', '2020-11-19', '2020-11-20', '2020-11-23', '2020-11-24', '2020-11-25', '2020-11-26', '2020-11-27', '2020-11-30', '2020-12-01', '2020-12-02', '2020-12-03', '2020-12-04', '2020-12-07', '2020-12-08', '2020-12-09', '2020-12-10', '2020-12-11', '2020-12-14', '2020-12-15', '2020-12-16', '2020-12-17', '2020-12-18', '2020-12-21', '2020-12-22', '2020-12-23', '2020-12-24', '2020-12-25', '2020-12-28', '2020-12-29', '2020-12-30', '2020-12-31', '2021-01-01', '2021-01-04', '2021-01-05', '2021-01-06', '2021-01-07', '2021-01-08', '2021-01-11', '2021-01-12', '2021-01-13', '2021-01-14', '2021-01-15', '2021-01-18', '2021-01-19', '2021-01-20', '2021-01-21', '2021-01-22', '2021-01-25', '2021-01-26', '2021-01-27', '2021-01-28', '2021-01-29', '2021-02-01', '2021-02-02', '2021-02-03', '2021-02-04', '2021-02-05', '2021-02-08', '2021-02-09', '2021-02-10', '2021-02-11', '2021-02-12', '2021-02-15', '2021-02-16', '2021-02-17', '2021-02-18', '2021-02-19', '2021-02-22', '2021-02-23', '2021-02-24', '2021-02-25', '2021-02-26', '2021-03-01', '2021-03-02', '2021-03-03', '2021-03-04', '2021-03-05', '2021-03-08', '2021-03-09', '2021-03-10', '2021-03-11', '2021-03-12', '2021-03-15', '2021-03-16', '2021-03-17', '2021-03-18', '2021-03-19', '2021-03-22', '2021-03-23', '2021-03-24', '2021-03-25', '2021-03-26', '2021-03-29', '2021-03-30', '2021-03-31', '2021-04-01', '2021-04-02', '2021-04-05', '2021-04-06', '2021-04-07', '2021-04-08', '2021-04-09', '2021-04-12', '2021-04-13', '2021-04-14', '2021-04-15', '2021-04-16', '2021-04-19', '2021-04-20', '2021-04-21', '2021-04-22', '2021-04-23', '2021-04-26', '2021-04-27', '2021-04-28', '2021-04-29', '2021-04-30', '2021-05-03', '2021-05-04', '2021-05-05', '2021-05-06', '2021-05-07', '2021-05-10', '2021-05-11', '2021-05-12', '2021-05-13', '2021-05-14', '2021-05-17', '2021-05-18', '2021-05-19', '2021-05-20', '2021-05-21', '2021-05-24', '2021-05-25', '2021-05-26', '2021-05-27', '2021-05-28', '2021-05-31', '2021-06-01', '2021-06-02', '2021-06-03', '2021-06-04', '2021-06-07', '2021-06-08', '2021-06-09', '2021-06-10', '2021-06-11', '2021-06-14', '2021-06-15', '2021-06-16', '2021-06-17', '2021-06-18', '2021-06-21', '2021-06-22', '2021-06-23', '2021-06-24', '2021-06-25', '2021-06-28', '2021-06-29', '2021-06-30']
Eliminate Queensland Holidays from Working Dates
Excluding The Royal Queensland Show [2020-08-14] Queensland holiday
Excluding Anzac Day (Observed) [2021-04-26] Queensland holiday
Excluding Labour Day [2021-05-03] Queensland holiday
Excluding Good Friday [2021-04-02] Queensland holiday
Excluding Boxing Day (Observed) [2020-12-28] Queensland holiday
Excluding Christmas Day [2020-12-25] Queensland holiday
Excluding Queen's Birthday [2020-10-05] Queensland holiday
Excluding Australia Day [2021-01-26] Queensland holiday
Excluding Easter Monday [2021-04-05] Queensland holiday
Excluding New Year's Day [2021-01-01] Queensland holiday
251 working days remaining
Eliminate Dates of Leave from Working Dates
Removing leave from working days: ['2020-12-24', '2020-12-29', '2020-12-30', '2020-12-31', '2021-04-06', '2021-04-07', '2021-04-28', '2021-04-29', '2021-05-24']
242 working days remaining
Discover working days during lockdowns
The 2020 First Lockdown (98 Days) dates ['2020-07-01', '2020-07-02', '2020-07-03', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09', '2020-07-10', '2020-07-13'] were worked from home
The 2021-W01 Lockdown (January) dates ['2021-01-08', '2021-01-11', '2021-01-12'] were worked from home
The 2021-W13 Lockdown (Easter Lead-up) dates ['2021-03-29', '2021-03-30', '2021-03-31', '2021-04-01'] were worked from home
The 2021-W26 Lockdown (June) dates ['2021-06-29', '2021-06-30'] were worked from home
Discover working days during work partial work from home period
Work from home period dates: ['2020-07-14', '2020-07-17', '2020-07-21', '2020-07-24', '2020-07-28', '2020-07-31', '2020-08-04', '2020-08-07', '2020-08-11', '2020-08-18', '2020-08-21', '2020-08-25', '2020-08-28', '2020-09-01', '2020-09-04', '2020-09-08', '2020-09-11', '2020-09-15', '2020-09-18', '2020-09-22', '2020-09-25', '2020-09-29', '2020-10-02', '2020-10-06', '2020-10-09', '2020-10-13', '2020-10-16', '2020-10-20', '2020-10-23', '2020-10-27', '2020-10-30', '2020-11-03', '2020-11-06', '2020-11-10', '2020-11-13', '2020-11-17', '2020-11-20', '2020-11-24', '2020-11-27', '2020-12-01', '2020-12-04', '2020-12-08', '2020-12-11', '2020-12-15', '2020-12-18', '2020-12-22', '2021-01-05', '2021-01-08', '2021-01-12', '2021-01-15', '2021-01-19', '2021-01-22', '2021-01-29', '2021-02-02', '2021-02-05', '2021-02-09', '2021-02-12', '2021-02-16', '2021-02-19', '2021-02-23', '2021-02-26', '2021-03-02', '2021-03-05', '2021-03-09', '2021-03-12', '2021-03-16', '2021-03-19', '2021-03-23', '2021-03-26', '2021-04-09', '2021-04-13', '2021-04-16', '2021-04-20', '2021-04-23', '2021-04-27', '2021-04-30', '2021-05-04', '2021-05-07', '2021-05-11', '2021-05-14', '2021-05-18', '2021-05-21', '2021-05-25', '2021-05-28', '2021-06-01', '2021-06-04', '2021-06-08', '2021-06-11', '2021-06-15', '2021-06-18', '2021-06-22', '2021-06-25', '2021-06-29']
Total Work From Home Days: 108
List of Work From Home Days: ['2020-07-01', '2020-07-02', '2020-07-03', '2020-07-06', '2020-07-07', '2020-07-08', '2020-07-09', '2020-07-10', '2020-07-13', '2020-07-14', '2020-07-17', '2020-07-21', '2020-07-24', '2020-07-28', '2020-07-31', '2020-08-04', '2020-08-07', '2020-08-11', '2020-08-18', '2020-08-21', '2020-08-25', '2020-08-28', '2020-09-01', '2020-09-04', '2020-09-08', '2020-09-11', '2020-09-15', '2020-09-18', '2020-09-22', '2020-09-25', '2020-09-29', '2020-10-02', '2020-10-06', '2020-10-09', '2020-10-13', '2020-10-16', '2020-10-20', '2020-10-23', '2020-10-27', '2020-10-30', '2020-11-03', '2020-11-06', '2020-11-10', '2020-11-13', '2020-11-17', '2020-11-20', '2020-11-24', '2020-11-27', '2020-12-01', '2020-12-04', '2020-12-08', '2020-12-11', '2020-12-15', '2020-12-18', '2020-12-22', '2021-01-05', '2021-01-08', '2021-01-11', '2021-01-12', '2021-01-15', '2021-01-19', '2021-01-22', '2021-01-29', '2021-02-02', '2021-02-05', '2021-02-09', '2021-02-12', '2021-02-16', '2021-02-19', '2021-02-23', '2021-02-26', '2021-03-02', '2021-03-05', '2021-03-09', '2021-03-12', '2021-03-16', '2021-03-19', '2021-03-23', '2021-03-26', '2021-03-29', '2021-03-30', '2021-03-31', '2021-04-01', '2021-04-09', '2021-04-13', '2021-04-16', '2021-04-20', '2021-04-23', '2021-04-27', '2021-04-30', '2021-05-04', '2021-05-07', '2021-05-11', '2021-05-14', '2021-05-18', '2021-05-21', '2021-05-25', '2021-05-28', '2021-06-01', '2021-06-04', '2021-06-08', '2021-06-11', '2021-06-15', '2021-06-18', '2021-06-22', '2021-06-25', '2021-06-29', '2021-06-30']
#!/usr/bin/env python3
from datetime import date
import numpy as np
import pandas as pd
import holidays
"""
work_from_home is a script to calculate the days worked from home for tax purposes
variables define days of leave, lockdown periods and partial work from home periods
"""
tax_year_start = date.fromisoformat('2020-07-01')
tax_year_end = date.fromisoformat('2021-06-30')
"""
weekmaskstr or array_like of bool, optional
A seven-element array indicating which of Monday through Sunday are valid days. May be specified as a length-seven list or array, like [1,1,1,1,1,0,0];
a length-seven string, like ‘1111100’; or a string like “Mon Tue Wed Thu Fri”, made up of 3-character abbreviations for weekdays, optionally separated by white space.
Valid abbreviations are: Mon Tue Wed Thu Fri Sat Sun
"""
# worked tuesday and friday from home during partial wfh
wfh_weekmask = '0100100'
# range of dates I worked from home not in lockdown
wfh_periods = [
(date.fromisoformat('2020-07-13'), date.fromisoformat('2021-01-08')),
(date.fromisoformat('2021-01-12'), date.fromisoformat('2021-03-29')),
(date.fromisoformat('2021-04-02'), date.fromisoformat('2021-06-29')),
]
leave = [
(date.fromisoformat('2020-12-24'), date.fromisoformat('2020-12-24')),
(date.fromisoformat('2020-12-29'), date.fromisoformat('2020-12-31')),
(date.fromisoformat('2021-04-06'), date.fromisoformat('2021-04-07')),
(date.fromisoformat('2021-04-28'), date.fromisoformat('2021-04-29')),
(date.fromisoformat('2021-05-24'), date.fromisoformat('2021-05-24'))
]
lockdowns = {
'2020 First Lockdown (98 Days)': (date.fromisoformat('2020-07-01'), date.fromisoformat('2020-07-13')),
'2021-W01 Lockdown (January)': (date.fromisoformat('2021-01-08'), date.fromisoformat('2021-01-12')),
'2021-W13 Lockdown (Easter Lead-up)': (date.fromisoformat('2021-03-29'), date.fromisoformat('2021-04-02')),
'2021-W26 Lockdown (June)': (date.fromisoformat('2021-06-29'), date.fromisoformat('2021-07-04'))
}
# collect all the work from home into this final set
wfh_dates = set()
if __name__ == "__main__":
"""
Calculates the number of working days each year worked from home during lockdowns & partial WFH periods
"""
print(f"\nDiscover all Working Days in Mon-Fri Pattern\n")
# busday_count is exclusive of end date
working_day_count = np.busday_count(tax_year_start.isoformat(), tax_year_end.isoformat())+1
# first discover all the working days
working_days = set()
for d in pd.date_range(tax_year_start,tax_year_end,freq='d'):
#print(d.strftime("%Y-%m-%d"))
if np.is_busday(d.strftime("%Y-%m-%d")):
working_days.add(d)
print(f"Number of working days for set: {len(working_days)}, numpy: {working_day_count} should match")
print(f"Set working days: {[d.strftime('%Y-%m-%d') for d in sorted(working_days)]}")
# if date is public holidays, remove from the set
print(f"\nEliminate Queensland Holidays from Working Dates\n")
# import queensland public holidays
qld_holidays = holidays.Australia(prov='QLD')
remove_dates = []
for d in working_days:
if d.strftime('%Y-%m-%d') in qld_holidays:
print(f"Excluding {qld_holidays.get(d.strftime('%Y-%m-%d'))} [{d.strftime('%Y-%m-%d')}] Queensland holiday")
remove_dates.append(d)
for d in remove_dates:
working_days.remove(d)
print(f"{len(working_days)} working days remaining")
# generate set of leave dates, and remove from working day set
print(f"\nEliminate Dates of Leave from Working Dates\n")
remove_dates = []
for l in leave:
for d in pd.date_range(l[0],l[1],freq='d'):
if d in working_days:
remove_dates.append(d)
print(f"Removing leave from working days: {[d.strftime('%Y-%m-%d') for d in sorted(remove_dates)]}")
for d in remove_dates:
working_days.remove(d)
print(f"{len(working_days)} working days remaining")
# find all working days during the lockdown periods
print(f"\nDiscover working days during lockdowns\n")
for k in lockdowns:
worked_dates = []
for d in pd.date_range(lockdowns[k][0],lockdowns[k][1],freq='d'):
if d in working_days:
worked_dates.append(d)
wfh_dates.add(d)
print(f"The {k} dates {[d.strftime('%Y-%m-%d') for d in sorted(worked_dates)]} were worked from home")
# find all working days during the partial WFH periods using the wfh_weekmask
print(f"\nDiscover working days during work partial work from home period\n")
worked_dates = []
for t in wfh_periods:
for d in pd.date_range(t[0],t[1],freq='d'):
if d in working_days and np.is_busday(d.strftime("%Y-%m-%d"), weekmask=wfh_weekmask):
worked_dates.append(d)
wfh_dates.add(d)
print(f"Work from home period dates: {[d.strftime('%Y-%m-%d') for d in sorted(worked_dates)]}")
# returning results
print(f"\nTotal Work From Home Days: {len(wfh_dates)}")
print(f"\nList of Work From Home Days: {[d.strftime('%Y-%m-%d') for d in sorted(wfh_dates)]}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment