如何在Python中获取下个月的第一天?

问题描述 投票:0回答:11

如何在Python中获取下个月的第一个日期?例如,如果现在是 2019-12-31,则下个月的第一天是 2020-01-01。如果现在是 2019-08-01,那么下个月的第一天就是 2019-09-01。

我想出了这个:

import datetime

def first_day_of_next_month(dt):
    '''Get the first day of the next month. Preserves the timezone.

    Args:
        dt (datetime.datetime): The current datetime

    Returns:
        datetime.datetime: The first day of the next month at 00:00:00.
    '''
    if dt.month == 12:
        return datetime.datetime(year=dt.year+1,
                                 month=1,
                                 day=1,
                                 tzinfo=dt.tzinfo)
    else:
        return datetime.datetime(year=dt.year,
                                 month=dt.month+1,
                                 day=1,
                                 tzinfo=dt.tzinfo)


# Example usage (assuming that today is 2021-01-28):
first_day_of_next_month(datetime.datetime.now())
# Returns: datetime.datetime(2021, 2, 1, 0, 0)

正确吗?有更好的办法吗?

python python-datetime
11个回答
83
投票

这是一个仅使用标准

datetime
库的 1 行解决方案:

(dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1)

示例:

>>> dt = datetime.datetime(2016, 2, 29)
>>> print((dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1))
2016-03-01 00:00:00

>>> dt = datetime.datetime(2019, 12, 31)
>>> print((dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1))
2020-01-01 00:00:00

>>> dt = datetime.datetime(2019, 12, 1)
>>> print((dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1))
2020-01-01 00:00:00

19
投票

使用

dateutil
你可以做到最字面意义上的:

import datetime
from dateutil import relativedelta
today = datetime.date.today()

next_month = today + relativedelta.relativedelta(months=1, day=1)

英语:在今天的日期上添加 1 个月,并将(该月的)日期设置为 1。注意

day(s)
month(s)
的单数和复数形式的用法。单数将属性设置为一个值,复数添加句点数量。

您可以将此

relativedelta.relativedelta
对象存储到变量中并将其传递。其他答案涉及更多编程逻辑。

编辑你也可以使用标准的

datetime
库来做到这一点,但它不是那么漂亮:

next_month = (today.replace(day=1) + datetime.timedelta(days=32)).replace(day=1)

将日期设置为当月 1 号,添加 32 天(或 31 到 59 之间的任何数字,保证跳到下个月),然后将日期设置为该月的 1 号。


12
投票

您可以使用

calendar
获取给定月份的天数,然后添加
timedelta(days=...)
,如下所示:

from datetime import date, timedelta
from calendar import monthrange

days_in_month = lambda dt: monthrange(dt.year, dt.month)[1]
today = date.today()
first_day = today.replace(day=1) + timedelta(days_in_month(today))
print(first_day)

如果您对外部部门感到满意,您可以使用 dateutil(我喜欢...)

from datetime import date
from dateutil.relativedelta import relativedelta

today = date.today()
first_day = today.replace(day=1) + relativedelta(months=1)
print(first_day)

3
投票

提取年月,加1,年月日=1形成一个新的日期:

from datetime import date

now       = date(2020,12,18)
y,m       = divmod(now.year*12+now.month,12)
nextMonth = date(y,m+1,1)

print(now,nextMonth)
# 2020-12-18 2021-01-01

1
投票

你的方式看起来不错,但我会这样做:

import datetime
from dateutil import relativedelta

dt = datetime.datetime(year=1998,
                             month=12,
                             day=12)

nextmonth = dt + relativedelta.relativedelta(months=1)
nextmonth.replace(day=1)
print(nextmonth)

1
投票

python-dateutil

from datetime import date
from dateutil.relativedelta import relativedelta

本月最后一天:

date.today() + relativedelta(day=31)

下个月的第一天:

date.today() + relativedelta(day=31) + relativedelta(days=1)

0
投票

仅使用Python标准库:

import datetime
today = datetime.date.today()
first_of_next_month = return date.replace(
    day=1,
    month=date.month % 12 + 1,
    year=date.year + (date.month // 12)
)

可以推广到...

def get_first_of_month(date, month_offset=0):
    # zero based indexing of month to make math work
    month_count = date.month - 1 + month_offset
    return date.replace(
        day=1, month=month_count % 12 + 1, year=date.year + (month_count // 12)
    )

first_of_next_month = get_first_of_month(today, 1)

其他不需要第三方库的解决方案包括:

  • 托比·佩蒂的回答是另一个不错的选择。
  • 如果确切的时间增量对您有帮助, 对Adam.Er8的答案稍作修改可能会很方便:
    import calendar, datetime
    
    today = datetime.date.today()
    time_until_next_month = datetime.timedelta(
        calendar.monthrange(today.year, today.month)[1] - today.day + 1
    )
    first_of_next_month = today + time_until_next_month
    

0
投票

使用 Zope 的 DateTime 库,可以实现非常简单的解决方案

from DateTime.DateTime import DateTime

date = DateTime()  # today

while date.day() != 1:
    date += 1

print(date)

0
投票

我看到这个问题有很多精彩的解决方案,当我偶然发现这个问题时,我个人正在寻找一个解决方案来获取上个月的第一天和最后一天。

但我认为这是一个非常简单而优雅的解决方案:

date = datetime.datetime.now().date()
same_time_next_month = date + datetime.timedelta(days = date.day)
first_day_of_next_month_from_date = same_time_next_month - datetime.timedelta(days = same_time_next_month.day - 1)

这里我们简单地将目标日期的天数添加到日期中即可获得下个月的相同时间,然后从获得的新日期中删除经过的天数。


0
投票

尝试一下,对于每个月的开始日期,将

MonthEnd(1)
更改为
MonthBegin(1)

import pandas as pd
from pandas.tseries.offsets import MonthBegin, MonthEnd

date_list = (pd.date_range('2021-01-01', '2022-01-31', 
              freq='MS') + MonthEnd(1)).strftime('%Y-%m-%d').tolist()
date_list

出:

['2021-01-31',
 '2021-02-28',
 '2021-03-31',
 '2021-04-30',
 '2021-05-31',
 '2021-06-30',
 '2021-07-31',
 '2021-08-31',
 '2021-09-30',
 '2021-10-31',
 '2021-11-30',
 '2021-12-31',
 '2022-01-31']

0
投票

我想出的另一句话:

datetime(year=dt.year + (dt.month==12), month=1 + dt.month % 12, day=1)
© www.soinside.com 2019 - 2024. All rights reserved.