Created
July 9, 2024 15:29
-
-
Save bbengfort/49c34158959bf015714abf0efa02ae3e to your computer and use it in GitHub Desktop.
Compute per-diem for travel based on GSA M&IE (Meals and Incidental Expenses)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
from tabulate import tabulate | |
from datetime import datetime, timedelta | |
DATE_FMT = "%Y-%m-%d" | |
ONE_DAY = timedelta(days=1) | |
def main(args): | |
start = datetime.strptime(args.start, DATE_FMT) | |
end = datetime.strptime(args.end, DATE_FMT) | |
mie = args.rate | |
travel = 0.75*mie | |
# Show the detail of the computation | |
if args.detail: | |
table = [] | |
total = 0.0 | |
day = start | |
while day != end: | |
if day == start: | |
table.append([day.date(), travel]) | |
total += travel | |
else: | |
table.append([day.date(), mie]) | |
total += mie | |
day += ONE_DAY | |
# Handle the last day | |
total += travel | |
table.append([day.date(), travel]) | |
table.append(["total", total]) | |
print(tabulate(table)) | |
return | |
# Otherwise just do the computation | |
# Compute number of days in the trip inclusive of the start and end date | |
days = (end - start).days + 1 | |
if days == 1: | |
print(f"the per diem for one day is ${travel:0.2f}") | |
elif days == 2: | |
rate = travel*2 | |
print(f"the per diem for two days is ${rate:0.2f}") | |
else: | |
rate = (2*travel) + ((days-2)*mie) | |
print(f"the per diem for {days} days is ${rate:0.2f}") | |
if __name__ == "__main__": | |
args = { | |
("-s", "--start"): { | |
"type": str, "metavar": "YYYY-MM-DD", "required": True, | |
"help": "start date of the trip to compute MI&E for", | |
}, | |
("-e", "--end"): { | |
"type": str, "metavar": "YYYY-MM-DD", "required": True, | |
"help": "end date of the trip to compute MI&E for", | |
}, | |
("-r", "--rate"): { | |
"type": float, "metavar": "DD.CC", "required": True, | |
"help": "the MI&E rate from gsa.gov", | |
}, | |
("-d", "--detail"): { | |
"action": "store_true", "default": False, | |
"help": "print out a detail of the rate per day" | |
}, | |
} | |
parser = argparse.ArgumentParser( | |
description="compute MI&E per-diem for a specified date range", | |
epilog="the per-diem rate must be looked up on gsa.gov", | |
) | |
for pargs, kwargs in args.items(): | |
if isinstance(pargs, str): | |
pargs = (pargs,) | |
parser.add_argument(*pargs, **kwargs) | |
args = parser.parse_args() | |
main(args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment