5

曜日の名前である文字列 が与えられた場合reqDayOf、どのように曜日を 10 進数として計算しますか (そして、オブジェクトに基づいてその次のインスタンスを返しdatetimeます)?

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'
4

2 に答える 2

4

曜日 (整数として) は、weekday メソッドによって返されます。

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)
于 2013-04-05T13:17:43.747 に答える
2

これは、@unutbu の anwser の weekdayメソッドに似ていますが、曜日名 (またはその省略形) をハードコードする必要がない方法で実装されています。datetime.date'sメソッドを使用toordinal()して日付を単一の数値に変換し、希望の曜日を取得するために何日足すかを計算し、最後にdate.fromordinal()メソッドを使用して新しい数値を日付に戻します。

という名前の辞書を作成して使用し、曜日名を 1 から 7 までの数字DAYNUMSに変換します。このメソッドを使用して、渡された引数についても同様の処理を行います。ディクショナリは、ハードコードされた曜日名を使用せずに作成されるため、英語以外のロケールや適切な引数が与えられた言語(フランス語のロケールの代わりなど) でも機能します。reqDayOfdate.isoweekday()dateTimeObjDAYNUMSreqDayOf'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
于 2013-04-05T16:34:56.530 に答える