我有一个带有日期列的数据集。我想获取与每个日期关联的星期数。 我知道我可以使用:
x['date'].isocalendar()[1]
但这给了我星期几,开始日期=星期一。我需要一周从星期五开始。
您如何建议我继续这样做?
答案 0 :(得分:5)
“ ISO标准”和“ 您想要的”部分是为了阐明您的需求。
您只需将代码复制粘贴到“ 解决方案”部分中,然后查看结果是否是您想要的。
定义
Python标准库datetime
>>> datetime(2020, 1, 1).isocalendar()
(2020, 1, 3) # The 3rd day of the 1st week in 2020
>>> datetime(2019, 12, 31).isocalendar()
(2020, 1, 2) # The 2nd day of the 1st week in 2020
>>> datetime(2019, 1, 1).isocalendar()
(2019, 1, 2)
>>> datetime(2017, 1, 1).isocalendar()
(2016, 52, 7)
>>> datetime(2016, 12, 26).isocalendar()
(2016, 52, 1)
>>> datetime(2015, 12, 31).isocalendar()
(2015, 53, 4)
>>> datetime(2016, 1, 1).isocalendar()
(2015, 53, 5)
日历草图
# Mo Tu Wd Th Fr Sa Sn
# [2019-52w] DEC/ 23 24 25 26 27 28 29 /DEC
# [2020-1w] DEC/ 30 31 1 2 3 4 5 /JAN
# [2019-1w] DEC/ 31 1 2 3 4 5 6 /JAN
# [2016-52w] DEC/ 26 27 28 29 30 31 1 /JAN
# [2015-53w] DEC/ 28 29 30 31 1 2 3 /JAN
# [2016-1w] JAN/ 4 5 6 7 8 9 10 /JAN
定义
日历草图
# Fr Sa Sn. Mo Tu Wd Th
# [2019-51w] DEC/ 20 21 22. 23 24 25 26 /DEC
# [2019-52w] DEC/ 27 28 29. 30 31 1 2 /JAN
# [2020-1w] JAN/ 3 4 5. 6 7 8 9 /JAN
# [2018-53w] DEC/ 28 29 30. 31 1 2 3 /JAN
# [2019-1w] JAN/ 4 5 6. 7 8 9 10 /JAN
# [2016-52w] DEC/ 23 24 25. 26 27 28 29 /DEC
# [2017-1w] DEC/ 30 31 1. 2 3 4 5 /JAN
# [2015-52w] DEC/ 25 26 27. 28 29 30 31 /DEC
# [2016-1w] JAN/ 1 2 3. 4 5 6 7 /JAN
from datetime import datetime, timedelta
from enum import IntEnum
WEEKDAY = IntEnum('WEEKDAY', 'MON TUE WED THU FRI SAT SUN', start=1)
class CustomizedCalendar:
def __init__(self, start_weekday, indicator_weekday=None):
self.start_weekday = start_weekday
self.indicator_delta = 3 if not (indicator_weekday) else (indicator_weekday - start_weekday) % 7
def get_week_start(self, date):
delta = date.isoweekday() - self.start_weekday
return date - timedelta(days=delta % 7)
def get_week_indicator(self, date):
week_start = self.get_week_start(date)
return week_start + timedelta(days=self.indicator_delta)
def get_first_week(self, year):
indicator_date = self.get_week_indicator(datetime(year, 1, 1))
if indicator_date.year == year: # The date "year.1.1" is on 1st week.
return self.get_week_start(datetime(year, 1, 1))
else: # The date "year.1.1" is on the last week of "year-1".
return self.get_week_start(datetime(year, 1, 8))
def calculate(self, date):
year = self.get_week_indicator(date).year
first_date_of_first_week = self.get_first_week(year)
diff_days = (date - first_date_of_first_week).days
return year, (diff_days // 7 + 1), (diff_days % 7 + 1)
if __name__ == '__main__':
# Use like this:
my_calendar = CustomizedCalendar(start_weekday=WEEKDAY.FRI, indicator_weekday=WEEKDAY.MON)
print(my_calendar.calculate(datetime(2020, 1, 2)))
我们可以简单地使用原始ISO设置初始化CustomizedCalendar
,然后验证结果是否与原始isocalendar()
的结果相同。
my_calendar = CustomizedCalendar(start_weekday=WEEKDAY.MON)
s = datetime(2019, 12, 19)
for delta in range(20):
print my_calendar.calculate(s) == s.isocalendar()
s += timedelta(days=1)
答案 1 :(得分:1)
这是最小的逻辑:
您只需要在星期一增加3天即可到达星期四。只需将日期添加到星期一,然后拨打ISO周号即可。您将获得转移的星期数。
from datetime import datetime, timedelta
x = datetime(2020, 1, 2) # this is Thursday and week 1 in ISO calendar; should be 1 in custom calendar w/ week starting Thu
y = datetime(2020, 1, 3) # this is Friday and week 1 in ISO calendar; should be 2 in custom calendar
print(x)
print(y)
def weeknum(dt):
return dt.isocalendar()[1]
def myweeknum(dt):
offsetdt = dt + timedelta(days=3); # you add 3 days to Mon to get to Thu
return weeknum(offsetdt);
print(weeknum(x));
print(myweeknum(x));
print(weeknum(y));
print(myweeknum(y));
输出:
2020-01-02 00:00:00
2020-01-03 00:00:00
1
1
1
2
答案 2 :(得分:0)
从下面复制函数,然后weeknumber(2020, 8, 21, 'Tuesday')
将为您提供2020年8月21日所在的星期数,从Tuesday
开始的周数,第一个{{1} }的星期编号为Tuesday
。
0
您可以对问题this answer使用this answer(取决于How can I select all of the Sundays for a year using Python?)来获取给定年份中的所有星期一,星期二,星期三,...星期日。
辅助功能:
# necessary imports
from datetime import date, timedelta
import time
或者,(使用this):
def weeknum(dayname):
if dayname == 'Monday': return 0
if dayname == 'Tuesday': return 1
if dayname == 'Wednesday':return 2
if dayname == 'Thursday': return 3
if dayname == 'Friday': return 4
if dayname == 'Saturday': return 5
if dayname == 'Sunday': return 6
我们将要使用的主要功能:
def weeknum(dayname):
return time.strptime('Sunday', "%A").tm_wday
现在要获取给定日期的星期数,请执行以下操作:
def alldays(year, whichDayYouWant):
d = date(year, 1, 1)
d += timedelta(days = (weeknum(whichDayYouWant) - d.weekday()) % 7)
while d.year == year:
yield d
d += timedelta(days = 7)
def weeknumber(year, month, day, weekstartsonthisday):
specificdays = [d for d in alldays(year, weekstartsonthisday)]
return len([specificday for specificday in specificdays if specificday <= datetime.date(year,month,day)])
是一年中与specificdays
相同的工作日中datetime.date
个对象的列表。例如,weekstartsonthisday
像这样开始:
[d for d in alldays(2020,'Tuesday')]
提醒一下,2020年是这样的:
列表[datetime.date(2020, 1, 7),
datetime.date(2020, 1, 14),
datetime.date(2020, 1, 21),
datetime.date(2020, 1, 28),
datetime.date(2020, 2, 4),
...
将包含在您的日期之前的给定年份发生的[specificday for specificday in specificdays if specificday <= datetime.date(year,month,day)]
(例如,星期一,星期二,...,以您指定的为准)的列表。 len()会给我们星期几。第一个specificday
之前的一年中的第几天是specificday
周。
几个例子:
0
返回:weeknumber(2020,1,1,'Tuesday')
0
返回:weeknumber(2020,1,6,'Tuesday')
0
返回:weeknumber(2020,1,7,'Tuesday')
1
返回:weeknumber(2020,12,31,'Tuesday')
52
返回:weeknumber(2020,1,1,'Wednesday')
看起来不错。
答案 3 :(得分:0)
如果您希望每个日期的年份都恰好是日期本身的年份,则还有另一种形式的星期定义,如下所示。
# Mo Tu Wd Th Fr Sa Sn
# [2019-52w] DEC/ 23 24 25 26 27 28 29
# [2019-53w] DEC/ 30 31
# [2020-1w] JAN/ 1 2 3 4 5
# [2020-2w] JAN/ 6 7 8 9 10 11 12
# [2018-53w] DEC/ 31
# [2019-1w] JAN/ 1 2 3 4 5 6
# Fr Sa Sn. Mo Tu Wd Th
# [2019-53w] DEC/ 27 28 29. 30 31
# [2020-1w] JAN/ 1 2
# [2020-2w] JAN/ 3 4 5. 6 7 8 9
# [2018-53w] DEC/ 28 29 30. 31
# [2019-1w] JAN/ 1 2 3
# [2019-2w] JAN/ 4 5 6. 7 8 9 10
from datetime import datetime, timedelta
from enum import IntEnum
WEEKDAY = IntEnum('WEEKDAY', 'MON TUE WED THU FRI SAT SUN', start=1)
def get_week_number(start, date):
year_start = datetime(date.year, 1, 1) - timedelta(days=(datetime(date.year, 1, 1).isoweekday() - start) % 7)
return date.year, (date-year_start).days // 7 + 1, (date-year_start).days % 7 + 1
if __name__ == '__main__':
# usage:
print(get_week_number(WEEKDAY.FRI, datetime(2018, 12, 19)))