Get Last Day of the Month in Python
是否有一种方法可以使用Python的标准库轻松确定(即一个函数调用)给定月份的最后一天?
如果标准库不支持,那么dateutil包是否支持此功能?
我之前在查看日历模块的文档时没有注意到这一点,但是一个名为Monthrange的方法提供了以下信息:
monthrange(year, month)
Returns weekday of first day of the month and number of days in month, for the specified year and month.
号
1 2 3 4 5 6 7 | >>> import calendar >>> calendar.monthrange(2002,1) (1, 31) >>> calendar.monthrange(2008,2) (4, 29) >>> calendar.monthrange(2100,2) (0, 28) |
所以:
1 | calendar.monthrange(year, month)[1] |
。
似乎是最简单的方法。
很明显,
1 2 3 | >>> from calendar import monthrange >>> monthrange(2012, 2) (2, 29) |
我以前的回答仍然有效,但显然是次优的。
如果不想导入
1 2 3 4 5 | import datetime def last_day_of_month(any_day): next_month = any_day.replace(day=28) + datetime.timedelta(days=4) # this will never fail return next_month - datetime.timedelta(days=next_month.day) |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >>> 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 |
。
编辑:请参阅@blair conrad的答案以获得更清洁的解决方案
1 2 3 4 | >>> import datetime >>> datetime.date (2000, 2, 1) - datetime.timedelta (days = 1) datetime.date(2000, 1, 31) >>> |
编辑:看看我的其他答案。它有一个比这个更好的实现,我把它留在这里,以防有人有兴趣看到一个可能"滚动您自己的"计算器。
@约翰·米利金给出了一个很好的答案,另外还有计算下个月第一天的复杂度。
以下不是特别优雅,但要想找出任何给定日期所在月份的最后一天,您可以尝试:
1 2 3 4 5 6 7 8 9 10 11 | 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) |
号
使用
例子:
1 2 3 4 5 6 | from datetime 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) |
号
使用
1 2 | from dateutil.relativedelta import relativedelta last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1) |
号
这样做的目的是得到一个月的第一天,然后用
另一种解决方案是这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
。
使用如下函数:
1 2 3 4 5 6 7 8 9 | >>> >>> 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) |
。
1 2 | from datetime import timedelta (any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1) |
号
1 2 3 4 5 6 7 8 9 10 11 12 | >>> 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 |
号
如果您愿意使用外部库,请访问http://crsmithdev.com/arrow/
然后,您可以通过以下方式获得每月的最后一天:
1 2 | import arrow arrow.utcnow().ceil('month').date() |
这将返回一个日期对象,然后可以对其进行操作。
为了得到这个月的最后一个日期,我们这样做:
1 2 3 | from datetime import date, timedelta import calendar last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1]) |
现在,为了解释我们在这里所做的工作,我们将把它分为两部分:
首先是得到本月使用Monthrange的天数,Blair Conrad已经提到了他的解决方案:
1 | calendar.monthrange(date.today().year, date.today().month)[1] |
第二个是获取最后一个日期本身,这是我们在替换的帮助下完成的,例如
1 2 3 4 | >>> date.today() datetime.date(2017, 1, 3) >>> date.today().replace(day=31) datetime.date(2017, 1, 31) |
当我们按照上面提到的方法组合它们时,我们得到了一个动态解。
1 2 3 4 5 6 7 | import datetime now = datetime.datetime.now() start_month = datetime.datetime(now.year, now.month, 1) date_on_next_month = start_month + datetime.timedelta(35) start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1) last_day_month = start_next_month - datetime.timedelta(1) |
号
最简单的方法(不必导入日历)是获取下个月的第一天,然后从中减去一天。
1 2 3 4 5 6 7 | 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 |
输出:
1 | datetime.datetime(2017, 11, 30, 0, 0) |
。
PS:与
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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) |
输出:
1 2 | Time Spent= 0:00:00.097814 Time Spent= 0:00:00.109791 |
。
此代码假定您需要一个月最后一天的日期(即,不只是dd部分,而是整个yyyymmdd日期)
对我来说,这是最简单的方法:
1 2 3 4 5 6 | 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) |
号
在python 3.7中,有未记录的
1 2 3 4 5 6 | >>> calendar.monthlen(2002, 1) 31 >>> calendar.monthlen(2008, 2) 29 >>> calendar.monthlen(2100, 2) 28 |
。
它相当于记录的
你可以自己计算结束日期。简单的逻辑是从下个月的开始日期减去一天。:)
所以写一个自定义方法,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
打电话,
1 | end_date_of_a_month(datetime.datetime.now().date()) |
号
它将返回这个月的结束日期。将任何日期传递给此函数。返回该月的结束日期。
这是另一个答案。不需要额外的包裹。
1 | datetime.date(year + int(month/12), month%12+1, 1)-datetime.timedelta(days=1) |
得到下个月的第一天,从中减去一天。
我喜欢这边
1 2 3 4 5 | 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) |
号
使用熊猫!
1 2 3 4 5 6 7 8 9 | 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 |
号
这并不能解决主要问题,但是一个很好的办法就是使用
1 2 3 4 5 6 7 8 | # 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 |
。
整个
使用
你可以用relativedeltahttps://dateutil.readthedocs.io/en/stable/relativedelta.html网站埃多克斯1〔6〕这将给你最后一天。
如果你想做你自己的小功能,这是一个很好的起点:
1 2 3 4 5 6 7 | 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年
1 2 3 | import calendar from time import gmtime, strftime calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1] |
号
输出:
1 | 31 |
这将打印当前月份的最后一天。在本例中,是2016年5月15日。因此,您的输出可能会有所不同,但输出的天数将与当前月份的天数相同。如果你想通过每天运行cron作业来检查一个月的最后一天,那就太好了。
所以:
1 2 3 4 5 | import calendar from time import gmtime, strftime lastDay = calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1] today = strftime("%d", gmtime()) lastDay == today |
。
输出:
1 | False |
号
除非是这个月的最后一天。
如果在日期范围内传递,则可以使用此选项:
1 2 3 4 5 6 | 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 |
。
在下面的代码中,"get-last-day-u of-month(dt)"将给出这个值,日期采用字符串格式,如"yyyy-mm-dd"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import datetime def DateTime( d ): return datetime.datetime.strptime( d, '%Y-%m-%d').date() def RelativeDate( start, num_days ): d = DateTime( start ) return str( d + datetime.timedelta( days = num_days ) ) def get_first_day_of_month( dt ): return dt[:-2] + '01' def get_last_day_of_month( dt ): fd = get_first_day_of_month( dt ) fd_next_month = get_first_day_of_month( RelativeDate( fd, 31 ) ) return RelativeDate( fd_next_month, -1 ) |
。
下面是基于解决方案的python lambdas:
1 2 | next_month = lambda y, m, d: (y, m + 1, 1) if m + 1 < 13 else ( y+1 , 1, 1) month_end = lambda dte: date( *next_month( *dte.timetuple()[:3] ) ) - timedelta(days=1) |
我希望,它非常有用……用这种方法试试……我们必须要进口一些包装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import time from datetime import datetime, date from datetime import timedelta from dateutil import relativedelta start_date = fields.Date( string='Start Date', required=True, ) end_date = fields.Date( string='End Date', required=True, ) _defaults = { 'start_date': lambda *a: time.strftime('%Y-%m-01'), 'end_date': lambda *a: str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10], } |
号
我有一个简单的解决方案:
1 2 3 | import datetime datetime.date(2012,2, 1).replace(day=1,month=datetime.date(2012,2,1).month+1)-timedelta(days=1) datetime.date(2012, 2, 29) |