I\'m currently writing some reporting code that allows users to optionally specify a date range. The way it works (simplified), is:
from datetime import datetime, date, timedelta
def get_current_timestamp():
return int(datetime.now().timestamp())
def get_end_today_timestamp():
# get 23:59:59
result = datetime.combine(date.today() + timedelta(days=1), datetime.min.time())
return int(result.timestamp()) - 1
def get_datetime_from_timestamp(timestamp):
return datetime.fromtimestamp(timestamp)
end_today = get_datetime_from_timestamp(get_end_today_timestamp())
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)
After looking at some of the answers here, and not really finding anything extremely elegant, I did some poking around the standard library and found my current solution (which I like quite well): dateutil
.
Here's how I implemented it:
from datetime import date
from dateutil.relativedelta import relativedelta
now = date.today()
stop_time = now + relativedelta(days=1)
start_time = date(
# NOTE: I'm not doing dict.get() since in my implementation, these dict
# keys are guaranteed to exist.
year = options['year'] or now.year,
month = options['month'] or now.month,
day = options['day'] or now.day
)
if options['year']:
start_time = date(year=options['year'] or now.year, month=1, day=1)
stop_time = start_time + relativedelta(years=1)
if options['month']:
start_time = date(
year = options['year'] or now.year,
month = options['month'] or now.month,
day = 1
)
stop_time = start_time + relativedelta(months=1)
if options['day']:
start_time = date(
year = options['year'] or now.year,
month = options['month'] or now.month,
day = options['day'] or now.day,
)
stop_time = start_time + relativedelta(days=1)
# ... do stuff with start_time and stop_time here ...
What I like about this implementation, is that python's dateutil.relativedata.relativedata
works really well on edge cases. It gets the days/months/years correct. If I have month=12
, and do relativedata(months=1)
, it'll increment the year and set the month to 1 (works nicely).
Also: in the above implementation, if the user specifies none of the optional dates (year, month, or day)--we'll fallback to a nice default (start_time = this morning, stop_time = tonight), that way we'll default to doing stuff for the current day only.
Thanks to everyone for their answers--they were helpful in my research.
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)
today = datetime.date.today()
begintime = today.strftime("%Y-%m-%d 00:00:00")
endtime = today.strftime("%Y-%m-%d 23:59:59")
date = datetime.strftime('<input date str>')
date.replace(hour=0, minute=0, second=0, microsecond=0) # now we get begin of the day
date += timedelta(days=1, microseconds=-1) # now end of the day