给定一个字符串reqDayOf
,这是一个工作日名称,你如何计算工作日为十进制(然后根据datetime
对象返回它的下一个实例)?
获取datetime
对象的年份和iso年份,然后将strptime
与年份+周年+工作日名称一起使用,但感觉就像是黑客。
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'
答案 0 :(得分:5)
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)
或者,使用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
使用dateutil,您可以高层次地表达这个想法,而不必担心肮脏细节中的逐个错误,例如
DT.timedelta(days=(dow[reqDayOf.lower()]-weekday-1)%7+1)
答案 1 :(得分:2)
这与@unutbu's anwser中的工作日方法类似,但实现方式并不要求将日期名称(或其缩写)硬编码到其中。它使用datetime.date
' toordinal()
方法将日期转换为单个数字,然后计算添加到其中的天数以获得所需的工作日,最后转换新数字使用date.fromordinal()
方法返回日期。
它创建并使用名为DAYNUMS
的字典将reqDayOf
工作日名称转换为1到7之间的数字,date.isoweekday()
方法用于dateTimeObj
方法。 1}}传递给它的参数。 DAYNUMS
字典是在不使用硬编码日期名称的情况下创建的,因此在给定适当的reqDayOf
参数的情况下,它也适用于非英语语言环境和语言,例如'lundi'
而不是'Monday'
}用于法语区域设置。
import datetime
# Create dictionary based on fact that 2013-April-01 was a Monday.
DAYNUMS = {datetime.date(2013, 4, i).strftime('%A').lower(): i
for i in range(1, 8)}
def getDateFromDayOf(dateTimeObj, reqDayOf):
daysDiff = (DAYNUMS[reqDayOf.lower()] - dateTimeObj.isoweekday() - 1) % 7 + 1
return datetime.date.fromordinal(dateTimeObj.toordinal() + daysDiff)
a_date = datetime.datetime.strptime('2013-04-05', '%Y-%m-%d')
print(a_date.strftime('%a %Y %b %d')) # -> Fri 2013 Apr 05
print(getDateFromDayOf(a_date, 'Monday').strftime('%a %Y %b %d')) # -> Mon 2013 Apr 08