Given a string, reqDayOf
, that's a weekday name, how do you figure out weekday as decimal (and then return the next instance of it based on a datetime
object)?
Getting the datetime
object's year and iso Week of Year and then using strptime
with the year + week of year + the weekday name works, but it feels like a hack.
import datetime
def getDateFromDayOf(dateTimeObj,reqDayOf):
#reqDayOf is one of ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
#return the next instance of reqDayOf
#after dateTimeObj
#as a datetime object
#Get the WeekOfYear from dateTimeObj and then
#get the date based on Year + WeekOfYear + reqDayOf
(dtoYear,dtoIsoWeek,x)=dateTimeObj.isocalendar()
checkDate= '{}-{}-{}'.format( dtoYear,dtoIsoWeek,reqDayOf)
dateOfDay=datetime.datetime.strptime(checkDate,"%Y-%U-%A")
#return dateOfDay if it's greater than the original date
if dateOfDay > dateTimeObj:
return dateOfDay
else:
#this is needed on Sundays
#add a week
return dateOfDay + datetime.timedelta(days=7)
>>> datetime.datetime.now().strftime('%a %Y %b %d')
'Fri 2013 Apr 05'
>>> getDateFromDayOf(datetime.datetime.now(),'Monday').strftime('%a %Y %b %d')
'Mon 2013 Apr 08'
The day of the week (as an integer) is returned by the weekday method:
import datetime as DT
dow = dict(zip('monday tuesday wednesday thursday friday saturday sunday'.split(),
range(7)))
def getDateFromDayOf(dateTimeObj, reqDayOf):
weekday = dateTimeObj.weekday()
return dateTimeObj + DT.timedelta(days=(dow[reqDayOf.lower()]-weekday-1)%7+1)
In [90]: getDateFromDayOf(DT.datetime.now(), 'Monday').date()
Out[90]: datetime.date(2013, 4, 8)
In [91]: getDateFromDayOf(DT.datetime.now(), 'Tuesday').date()
Out[91]: datetime.date(2013, 4, 9)
In [92]: getDateFromDayOf(DT.datetime.now(), 'Friday').date()
Out[92]: datetime.date(2013, 4, 12)
Or, using dateutil,
import datetime as DT
import dateutil
import dateutil.relativedelta as rdelta
import dateutil.rrule as rrule
dow = dict(zip('monday tuesday wednesday thursday friday saturday sunday'.split(),
(getattr(rdelta, d) for d in 'MO TU WE TH FR SA SU'.split())))
def getDateFromDayOf(dateTimeObj, reqDayOf):
rr = rrule.rrule(
rrule.DAILY, # step by days
byweekday = dow[reqDayOf.lower()], # return only this day of the week
dtstart = dateTimeObj) # start on this day
res = rr.after(dateTimeObj, inc=False) # inc=False means don't include the dtstart day
return res
Using dateutil you can express the idea in a high-level manner, without having to worry about off-by-one errors in grubby details like
DT.timedelta(days=(dow[reqDayOf.lower()]-weekday-1)%7+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