2013-04-05 47 views
5

給定一個字符串(reqDayOf),這是一個星期幾的名字,你如何計算星期幾作爲十進制(然後返回基於日期時間對象的下一個實例)?Python:給定一個星期幾名稱的字符串,如何計算出星期幾爲十進制(及其出現的下一個日期)?

獲取datetime對象的year和iso Week of Year,然後使用帶年份+星期+年份+星期幾名稱的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' 

回答

5

一週的一天(作爲一個整數)由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) 

或者,使用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) 
+0

我在這裏學到了一些東西。謝謝! – Alex 2013-04-05 14:37:52

2

這是@unutbu's anwser類似平日的方法,但實施不同。它使用datetime.datatoordinal()方法將日期轉換爲單個數字,然後計算出需要將日期添加到所需的工作日,最後使用fromordinal()方法將新數字轉換回日期。

命名DAYNUMS字典用於將reqDayOf星期名稱轉換爲數字1到7,和isoweekday()用來爲這是在通過dateTimeObj說法也這樣做。在創建DAYNUMS字典不使用硬編碼日期名稱,並且以這種方式,它可以在非英語語言環境和語言中工作,給出適當的reqDayOf參數,如法語語言環境中的'lundi'

import datetime 

# April 1, 2013 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) 

now = datetime.datetime.now() 
print now.strftime('%a %Y %b %d') 
print getDateFromDayOf(now, 'Monday').strftime('%a %Y %b %d') 
相關問題