Python 如何得到一个月的最后一天?
有没有一种方法可以使用Python的标准库轻松确定(即一个函数调用)给定月份的最后一天Python 如何得到一个月的最后一天?,python,date,Python,Date,有没有一种方法可以使用Python的标准库轻松确定(即一个函数调用)给定月份的最后一天 如果标准库不支持这一点,dateutil包是否支持这一点?编辑:请参阅@Blair Conrad的答案以获得更干净的解决方案 编辑:请参阅。它有一个比这个更好的实现,我把它放在这里,以防有人对如何“滚动您自己的”计算器感兴趣 @约翰·米利金给出了一个很好的答案,计算下个月的第一天更为复杂 下面的内容并不特别优雅,但要计算出任何给定日期所在月份的最后一天,您可以尝试: def last_day_of_mont
如果标准库不支持这一点,dateutil包是否支持这一点?编辑:请参阅@Blair Conrad的答案以获得更干净的解决方案
编辑:请参阅。它有一个比这个更好的实现,我把它放在这里,以防有人对如何“滚动您自己的”计算器感兴趣 @约翰·米利金给出了一个很好的答案,计算下个月的第一天更为复杂 下面的内容并不特别优雅,但要计算出任何给定日期所在月份的最后一天,您可以尝试:
def last_day_of_month(date):
if date.month == 12:
return date.replace(day=31)
return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)
>>> last_day_of_month(datetime.date(2002, 1, 17))
datetime.date(2002, 1, 31)
>>> last_day_of_month(datetime.date(2002, 12, 9))
datetime.date(2002, 12, 31)
>>> last_day_of_month(datetime.date(2008, 2, 14))
datetime.date(2008, 2, 29)
提供以下信息:
日历。蒙特兰奇(年、月)返回指定年份和月份的月份第一天的工作日和月份天数 因此:
似乎是最简单的方法。另一个解决方案是这样做:
from datetime import datetime
def last_day_of_month(year, month):
""" Work out the last day of the month """
last_days = [31, 30, 29, 28, 27]
for i in last_days:
try:
end = datetime(year, month, i)
except ValueError:
continue
else:
return end.date()
return None
并使用如下功能:
>>>
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)
from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1)
from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])
这并没有解决主要问题,但是获取一个月中最后一个工作日的一个好方法是使用
calendar.monthcalendar
,它返回一个日期矩阵,以星期一作为第一列,星期天作为最后一列
# Some random date.
some_date = datetime.date(2012, 5, 23)
# Get last weekday
last_weekday = np.asarray(calendar.monthcalendar(some_date.year, some_date.month))[:,0:-2].ravel().max()
print last_weekday
31
整个[0:-2]
就是把周末专栏删掉并扔掉。月份之外的日期用0表示,因此max实际上会忽略这些日期
严格来说,使用
numpy.ravel
并不是必需的,但我讨厌仅仅依赖于numpy.ndarray.max
的约定,即如果不告诉数组计算哪个轴,它将使数组变平。如果您不想导入日历
模块,一个简单的两步函数也可以是:
import datetime
def last_day_of_month(any_day):
# this will never fail
# get close to the end of the month for any day, and add 4 days 'over'
next_month = any_day.replace(day=28) + datetime.timedelta(days=4)
# subtract the number of remaining 'overage' days to get last day of current month, or said programattically said, the previous day of the first of next month
return next_month - datetime.timedelta(days=next_month.day)
产出:
>>> for month in range(1, 13):
... print last_day_of_month(datetime.date(2012, month, 1))
...
2012-01-31
2012-02-29
2012-03-31
2012-04-30
2012-05-31
2012-06-30
2012-07-31
2012-08-31
2012-09-30
2012-10-31
2012-11-30
2012-12-31
这其实很容易
day=31
将始终返回当月的最后一天:
import datetime
from dateutil.relativedelta import relativedelta
date_in_feb = datetime.datetime(2013, 2, 21)
print(datetime.datetime(2013, 2, 21) + relativedelta(day=31)) # End-of-month
# datetime.datetime(2013, 2, 28, 0, 0)
使用安装dateutil
pip install python-datetutil
如果您想制作自己的小功能,这是一个很好的起点:
def eomday(year, month):
"""returns the number of days in a given month"""
days_per_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
d = days_per_month[month - 1]
if month == 2 and (year % 4 == 0 and year % 100 != 0 or year % 400 == 0):
d = 29
return d
为此,您必须了解闰年的规则:
- 每四年
- 除了每100年
- 但每400年一次
- 对我来说,这是最简单的方法:
selected_date = date(some_year, some_month, some_day)
if selected_date.month == 12: # December
last_day_selected_month = date(selected_date.year, selected_date.month, 31)
else:
last_day_selected_month = date(selected_date.year, selected_date.month + 1, 1) - timedelta(days=1)
使用
dateutil.relativedelta
您将得到月份的最后一个日期,如下所示:
>>>
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)
from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1)
from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])
我们的想法是获得一个月的第一天,然后使用relativedelta
提前一个月,返回一天,这样你就可以得到你想要的一个月的最后一天。使用熊猫
>>> import datetime
>>> import calendar
>>> date = datetime.datetime.now()
>>> print date
2015-03-06 01:25:14.939574
>>> print date.replace(day = 1)
2015-03-01 01:25:14.939574
>>> print date.replace(day = calendar.monthrange(date.year, date.month)[1])
2015-03-31 01:25:14.939574
def isMonthEnd(date):
return date + pd.offsets.MonthEnd(0) == date
isMonthEnd(datetime(1999, 12, 31))
True
isMonthEnd(pd.Timestamp('1999-12-31'))
True
isMonthEnd(pd.Timestamp(1965, 1, 10))
False
输出:31
False
这将打印当前月份的最后一天。在这个例子中,时间是2016年5月15日。因此,您的输出可能不同,但是输出的天数与当前月份的天数相同。如果您想通过运行每日cron作业来检查一个月的最后一天,那就太好了。 所以:
输出:
31
False
除非是这个月的最后一天。我更喜欢这种方式
import datetime
import calendar
date=datetime.datetime.now()
month_end_date=datetime.datetime(date.year,date.month,1) + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1] - 1)
要获取当月的最后日期,我们将执行以下操作:
>>>
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)
from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1)
from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])
现在,为了解释我们在这里所做的工作,我们将其分为两部分:
首先是获得当月我们使用的天数,布莱尔·康拉德已经提到了他的解决方案:
calendar.monthrange(date.today().year, date.today().month)[1]
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.offsets.MonthEnd(1)
第二个是得到最后的日期,这是我们借助于例如
当我们像上面提到的那样组合它们时,我们得到了一个动态的解决方案。您可以自己计算结束日期。简单的逻辑是从下个月的开始日期减去一天 所以写一个自定义方法
import datetime
def end_date_of_a_month(date):
start_date_of_this_month = date.replace(day=1)
month = start_date_of_this_month.month
year = start_date_of_this_month.year
if month == 12:
month = 1
year += 1
else:
month += 1
next_month_start_date = start_date_of_this_month.replace(month=month, year=year)
this_month_end_date = next_month_start_date - datetime.timedelta(days=1)
return this_month_end_date
召唤
end_date_of_a_month(datetime.datetime.now().date())
它将返回本月的结束日期。将任何日期传递给此函数。返回该月的结束日期 如果您愿意使用外部库,请退出 然后,您可以通过以下方式获得当月的最后一天:
import arrow
arrow.utcnow().ceil('month').date()
这将返回一个日期对象,然后您可以对其进行操作。最简单的方法(无需导入日历)是获取下个月的第一天,然后从中减去一天
import datetime as dt
from dateutil.relativedelta import relativedelta
thisDate = dt.datetime(2017, 11, 17)
last_day_of_the_month = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print last_day_of_the_month
输出:
datetime.datetime(2017, 11, 30, 0, 0)
PS:与导入日历方法相比,此代码运行速度更快;见下文:
import datetime as dt
import calendar
from dateutil.relativedelta import relativedelta
someDates = [dt.datetime.today() - dt.timedelta(days=x) for x in range(0, 10000)]
start1 = dt.datetime.now()
for thisDate in someDates:
lastDay = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print ('Time Spent= ', dt.datetime.now() - start1)
start2 = dt.datetime.now()
for thisDate in someDates:
lastDay = dt.datetime(thisDate.year,
thisDate.month,
calendar.monthrange(thisDate.year, thisDate.month)[1])
print ('Time Spent= ', dt.datetime.now() - start2)
输出:
Time Spent= 0:00:00.097814
Time Spent= 0:00:00.109791
此代码假定您想要一个月最后一天的日期(即不仅仅是DD部分,而是整个YYYYMMDD日期)如果您传入一个日期范围,您可以使用以下方法:
def last_day_of_month(any_days):
res = []
for any_day in any_days:
nday = any_day.days_in_month -any_day.day
res.append(any_day + timedelta(days=nday))
return res
这是另一个答案。不需要额外的包裹
datetime.date(year + int(month/12), month%12+1, 1)-datetime.timedelta(days=1)
取下个月的第一天,从中减去一天。您可以使用relativedelta
import datetime as dt
from dateutil.relativedelta import relativedelta
thisDate = dt.datetime(2017, 11, 17)
last_day_of_the_month = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print last_day_of_the_month
月底=+相对LTA(日=31)
这将为您提供最后一天。在Python 3.7中,有:
它相当于。这是我仅使用标准datetime库的最简单解决方案:
import datetime
def get_month_end(dt):
first_of_month = datetime.datetime(dt.year, dt.month, 1)
next_month_date = first_of_month + datetime.timedelta(days=32)
new_dt = datetime.datetime(next_month_date.year, next_month_date.month, 1)
return new_dt - datetime.timedelta(days=1)
最简单的方法是使用和一些日期数学,例如从下个月的第一天减去一天:
import datetime
def last_day_of_month(d: datetime.date) -> datetime.date:
return (
datetime.date(d.year + d.month//12, d.month % 12 + 1, 1) -
datetime.timedelta(days=1)
)
或者,您可以使用获取一个月的天数(考虑闰年),并相应地更新日期:
import calendar, datetime
def last_day_of_month(d: datetime.date) -> datetime.date:
return d.replace(day=calendar.monthrange(d.year, d.month)[1])
快速基准测试表明,第一个版本的速度明显更快:
In [14]: today = datetime.date.today()
In [15]: %timeit last_day_of_month_dt(today)
918 ns ± 3.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [16]: %timeit last_day_of_month_calendar(today)
1.4 µs ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
这是一个很长(易于理解)的版本,但考虑了闰年
干杯,
JK
到目前为止,我发现的最简单、最可靠的方法是:
from datetime import datetime
import calendar
days_in_month = calendar.monthrange(2020, 12)[1]
end_dt = datetime(2020, 12, days_in_month)
更简单地说:
import datetime
now = datetime.datetime.now()
datetime.date(now.year, 1 if now.month==12 else now.month+1, 1) - datetime.timedelta(days=1)
对我来说,更简单的方法是使用pandas(双线解决方案): 另一种方法是:取一个月的第一天,然后加上一个月,再贴现一天:
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.DateOffset(months=1) - pd.DateOffset(days=1)
太复杂了,打破了python禅宗的第三条规则。我个人喜欢relativedelta(月=+1,秒=-1)看起来更明显,你错了
datetime(2014,2,1)+relativedelta(days=31)
给出了datetime(2014,3,4,0,0)
…您使用了days=而不是day=last_day=(+relativedelta(day=31))。day
@CarMoreno Yes适用于闰年。试试(日期时间(2020,2,2)+相对时间(天=
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.DateOffset(months=1) - pd.DateOffset(days=1)