Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何得到一个月的最后一天?_Python_Date - Fatal编程技术网

Python 如何得到一个月的最后一天?

Python 如何得到一个月的最后一天?,python,date,Python,Date,有没有一种方法可以使用Python的标准库轻松确定(即一个函数调用)给定月份的最后一天 如果标准库不支持这一点,dateutil包是否支持这一点?编辑:请参阅@Blair Conrad的答案以获得更干净的解决方案 编辑:请参阅。它有一个比这个更好的实现,我把它放在这里,以防有人对如何“滚动您自己的”计算器感兴趣 @约翰·米利金给出了一个很好的答案,计算下个月的第一天更为复杂 下面的内容并不特别优雅,但要计算出任何给定日期所在月份的最后一天,您可以尝试: def last_day_of_mont

有没有一种方法可以使用Python的标准库轻松确定(即一个函数调用)给定月份的最后一天


如果标准库不支持这一点,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)