给定一个特定的日期,例如2011-07-02,我如何找到该日期之后的下一个星期一(或任何工作日)的日期?
import datetime
def next_weekday(d, weekday):
days_ahead = weekday - d.weekday()
if days_ahead <= 0: # Target day already happened this week
days_ahead += 7
return d + datetime.timedelta(days_ahead)
d = datetime.date(2011, 7, 2)
next_monday = next_weekday(d, 0) # 0 = Monday, 1=Tuesday, 2=Wednesday...
print(next_monday)
((day - today) + 7) % 7
来获取日期差。 - jstaab(day - today) % 7
。在减法中出现的负数将按您的预期进行处理。例如,-1 % 7
的结果为6
。 - Code-Apprentice以下是一个简洁且通用的替代方案,与上面略微复杂的答案相比。
def onDay(date, day):
"""
Returns the date of the next given weekday after
the given date. For example, the date of next Monday.
NB: if it IS the day we're looking for, this returns 0.
consider then doing onDay(foo, day + 1).
"""
days = (day - date.weekday() + 7) % 7
return date + datetime.timedelta(days=days)
%7
进行计算时,不需要 +7
。可以改为:onDay = lambda date, day: date + datetime.timedelta(days=(day-date.weekday())%7)
。 - Zach Siegeldatetime
包中有一个date
类(我个人经常导入),所以我将date
视为关键字,不给变量命名为date
。我会将代码更改为:onDay = lambda dt, day: dt + datetime.timedelta(days=(day-dt.weekday())%7)
,以提醒自己输入的格式应该是Python的datetime.date
变量。(同样地,在Javascript中,date
是一个标准类型,你不应该将变量命名为date
。) - Zach Siegeldate
本身就是星期一,更改为 onDay = lambda date, day: date + datetime.timedelta(days=(day-date.weekday()-1)%7+1)
。不太重要的是:2. 如果day
应该是值1..7而不是0..6表示星期一..星期日,则将date.weekday()
更改为date.isoweekday()
。 - ElRudi试一试
>>> dt = datetime(2011, 7, 2)
>>> dt + timedelta(days=(7 - dt.weekday()))
datetime.datetime(2011, 7, 4, 0, 0)
使用Python的datetime
类型,星期一用0
表示,星期日用6
表示。根据这个规则,下一个星期一是当前星期一后7天,星期二后6天,以此类推。
datetime
API的一些属性,这些属性只适用于查找星期一。由phihag
提供的代码更通用,可以查找任何即将到来的星期几。 - Dirkphihag
提供的代码呢?它可以实现你想要的功能:next_weekday(datetime.date(2013,1,1), 6)
是datetime.date(2013, 1, 6)
,也就是星期天。我的代码在(滥)用Python的datetime
API的某些属性方面很“可爱”,只回答了“找到下一个星期一”这个问题,但不足以回答“找到下一个xxx日”的问题。 - Dirkd + timedelta(6 - d.weekday() or 13 - d.weekday())
(如果Sunday == 6
是一周的最后一天,则等同于phihag的代码)。 - jfsimport datetime
def next_day(given_date, weekday):
day_shift = (weekday - given_date.weekday()) % 7
return given_date + datetime.timedelta(days=day_shift)
now = datetime.date(2018, 4, 15) # sunday
names = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday',
'saturday', 'sunday']
for weekday in range(7):
print(names[weekday], next_day(now, weekday))
将会打印:
monday 2018-04-16
tuesday 2018-04-17
wednesday 2018-04-18
thursday 2018-04-19
friday 2018-04-20
saturday 2018-04-21
sunday 2018-04-15
正如您所看到的,它正确地给出了下周一、二、三、四、五和六。它也理解2018-04-15
是星期天,并返回当前星期天而不是下一个。
我相信在7年后,您会发现这个答案非常有帮助;-)
另一种选择是使用rrule。
from dateutil.rrule import rrule, WEEKLY, MO
from datetime import date
next_monday = rrule(freq=WEEKLY, dtstart=date.today(), byweekday=MO, count=1)[0]
rrule文档:https://dateutil.readthedocs.io/en/stable/rrule.html
relativedelta
版本在给定日期之后的时间上运行良好。例如,当请求下一个星期一的 11:00,并且开始时间是星期一的 13:00 时,relativedelta
仍会返回过去的当天的 11:00 - 这个时间已经过去了。另一方面,rrule
查找 dtstart
之后的下一个实例。因此,对于 dtstart
是星期一的 10:00 的情况,它将正确返回星期一的 11:00,并且对于 dtstart
是星期一的 13:00 的情况,它将返回_下一个_星期一的 11:00。 - Nick K9import pandas as pd
import datetime
# 1. Getting the closest monday from a given date
date = datetime.date(2011, 7, 2)
closest_monday = pd.date_range(start=date, end=date + pd.offsets.Day(6), freq="W-MON")[
0
]
# 2. Adding a 'ClosestMonday' column with the closest monday for each row in
# a pandas df using apply. Requires you to have a 'Date' column in your df
def get_closest_monday(row):
return pd.date_range(
start=row.Date, end=row.Date + pd.offsets.Day(6), freq="W-MON"
)[0]
df = pd.DataFrame([datetime.date(2011, 7, 2)], columns=["Date"])
df["ClosestMonday"] = df.apply(lambda row: get_closest_monday(row), axis=1)
print(df)
date_range
+ W-MON
+ offsets.Day(6)
是查询“过去固定日期和现在之间的每个星期一”的最佳解决方案,而且完全不需要手动调整工作日。感谢!这个答案应该有更多的投票。 - ojdooffsets
in this example should be pd.offsets
- henrycjc>>> d = datetime.date(2011, 7, 2)
>>> while d.weekday() != 0: #0 for monday
... d += datetime.timedelta(days=1)
...
>>> d
datetime.date(2011, 7, 4)
dateutil 有一个特殊的功能来执行这种操作,这是我迄今为止见过的最优雅的方式。
from datetime import datetime
from dateutil.relativedelta import relativedelta, MO
first_monday_date = (datetime(2011,7,2) + relativedelta(weekday=MO(0))).date()
如果您需要日期时间,只需:
first_monday_date = datetime(2011,7,2) + relativedelta(weekday=MO(0))
import datetime
d = datetime.date(2011, 7, 2)
while d.weekday() != 0:
d += datetime.timedelta(1)
weekday = 0 ## Monday
dt = datetime.datetime.now().replace(hour=0, minute=0, second=0) ## or any specific date
days_remaining = (weekday - dt.weekday() - 1) % 7 + 1
next_dt = dt + datetime.timedelta(days_remaining)