I'm currently writing some reporting code that allows users to optionally specify a date range. The way it works (simplified), is:
Here's a code snippet, along with comments describing what I'd like to do:
from datetime import datetime, timedelta
# ...
now = datetime.now()
start_time = now.replace(hour=0, minute=0, second=0, microsecond=0)
stop_time = now
# If the user enters no year, month, or day--then we'll simply run a
# report that only spans the current day (from the start of today to now).
if options['year']:
    start_time = start_time.replace(year=options['year'], month=0, day=0)
    stop_time = stop_time.replace(year=options['year'])
    # If the user specifies a year value, we should set stop_time to the last
    # day / minute / hour / second / microsecond of the year, that way we'll
    # only generate reports from the start of the specified year, to the end
    # of the specified year.
if options['month']:
    start_time = start_time.replace(month=options['month'], day=0)
    stop_time = stop_time.replace(month=options['month'])
    # If the user specifies a month value, then set stop_time to the last
    # day / minute / hour / second / microsecond of the specified month, that
    # way we'll only generate reports for the specified month.
if options['day']:
    start_time = start_time.replace(day=options['day'])
    stop_time = stop_time.replace(day=options['day'])
    # If the user specifies a day value, then set stop_time to the last moment of
    # the current day, so that reports ONLY run on the current day.
I'm trying to find the most elegant way to write the code above--I've been trying to find a way to do it with timedelta, but can't seem to figure it out. Any advice would be appreciated.
Using dict.get can simplify your code.  It is a bit cleaner than using datetime.replace and timedelta objects.
Here's something to get you started:
from datetime import datetime
options = dict(month=5, day=20)
now = datetime.now()
start_time = datetime(year=options.get('year', now.year), 
                      month=options.get('month', 1),
                      day=options.get('day', 1)
                      hour=0,
                      minute=0,
                      second=0)
stop_time =  datetime(year=options.get('year', now.year), 
                      month=options.get('month', now.month),
                      day=options.get('day', now.day),
                      hour=now.hour,
                      minute=now.minute,
                      second=now.second)
To set the stop_time, advance start_time one year, month or day as appropriate, then subtract one timedelta(microseconds=1)
if options['year']:
    start_time = start_time.replace(year=options['year'], month=1, day=1)
    stop_time = stop_time.replace(year=options['year']+1)-timedelta(microseconds=1)
elif options['month']:
    start_time = start_time.replace(month=options['month'], day=1)
    months=options['month']%12+1
    stop_time = stop_time.replace(month=months,day=1)-timedelta(microseconds=1)
else:
    start_time = start_time.replace(day=options['day'])
    stop_time = stop_time.replace(day=options['day'])+timedelta(days=1,microseconds=-1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With