Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.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
你如何加上?“;“3个月”;在python中创建datetime.date对象? Python日期计算,你在哪里?_Python_Sql_Postgresql - Fatal编程技术网

你如何加上?“;“3个月”;在python中创建datetime.date对象? Python日期计算,你在哪里?

你如何加上?“;“3个月”;在python中创建datetime.date对象? Python日期计算,你在哪里?,python,sql,postgresql,Python,Sql,Postgresql,我有一个python应用程序,需要在几年内每三个月绘制一次日期。重要的是,日期一年发生4次,并且日期尽可能多地发生在每年的同一天,日期尽可能多地发生在当月的同一天,并且日期之间的间隔尽可能接近“3个月”(这是一个移动目标,尤其是在闰年)。不幸的是,datetime.timedelta不支持月份 在python中有“标准”的计算方法吗 SQL方式? 如果出现最坏的情况,我会用我的应用程序问PostgreSQL,他确实有很好的内置日期计算支持,回答如下: # select ('2010-11-29'

我有一个python应用程序,需要在几年内每三个月绘制一次日期。重要的是,日期一年发生4次,并且日期尽可能多地发生在每年的同一天,日期尽可能多地发生在当月的同一天,并且日期之间的间隔尽可能接近“3个月”(这是一个移动目标,尤其是在闰年)。不幸的是,
datetime.timedelta
不支持月份

在python中有“标准”的计算方法吗

SQL方式? 如果出现最坏的情况,我会用我的应用程序问PostgreSQL,他确实有很好的内置日期计算支持,回答如下:

# select ('2010-11-29'::date + interval '3 months')::date;
    date    
------------
 2011-02-28
(1 row)
然后将每年的新年“正常化”到原来的日期(2月29日除外)

这里有一个好的解决方案

编辑
啊,很抱歉…

如果你想找准确的或“更准确的”日期,你最好还是离开

快速示例:

>>> from dateutil.relativedelta import relativedelta
>>> import datetime
>>> TODAY = datetime.date.today()
>>> TODAY
datetime.date(2012, 3, 6)
现在给今天的
加上3个月
,观察它是否与当天完全匹配(注意
relativedelta(月=3)
relativedelta(月=3)
有不同的行为。确保对这些示例使用
months

并且在一年中保持一致。事实上,每三个月一次,在当天(由于某种原因,必须将
relativedelta相乘并将其添加到
datetime中。date
对象抛出一个
TypeError
):

然而,作者建议的解决方案,虽然肯定“足够好”,但随着时间的推移会有轻微的漂移:

>>> three_mon_timedelta = datetime.timedelta(days=3 * 365/12)
>>> TODAY + three_mon_timedelta
datetime.date(2012, 6, 5)
在一年中,一个月中的哪一天一直在下滑:

>>> TODAY + three_mon_timedelta * 2
datetime.date(2012, 9, 4)
>>> TODAY + three_mon_timedelta * 3
datetime.date(2012, 12, 4)
>>> TODAY + three_mon_timedelta * 4
datetime.date(2013, 3, 5)

使用Python标准库,即不使用
dateutil
或其他库,并解决“2月31日”问题:

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date
测试:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))

我没有足够的声誉来评论。所以,我要写一个解决方案,修复David Ragazzi发布的解决方案中的一个bug

当您添加足够多的月份以到达十二月日期时,会发生此错误。这一年太多了

例如,
add_months(date.fromsofisoformat('2020-01-29'),11)
返回2021而不是2020。我通过更改以
year=
开头的行,解决了这个问题

    import datetime
    import calendar
    def add_months(dateInput, months):
        months_count = dateInput.month + months

        # Calculate the year
        year = dateInput.year + int((months_count-1) / 12)

        # Calculate the month
        month = (months_count % 12)
        if month == 0:
            month = 12

        # Calculate the day
        day = dateInput.day
        last_day_of_month = calendar.monthrange(year, month)[1]
        if day > last_day_of_month:
            day = last_day_of_month

        new_date = date(year, month, day)
        return new_date

来自@david ragazzi和@mikedugas77的答案对于
月份的正值很有效,但如果
月份我编写了这个函数,它可能会帮助您:

import datetime
import calendar

def add_months(date, months):

    # Determine the month and year of the new date
    month, year = (date + relativedelta(months=months)).month, (date + relativedelta(months=months)).year

    # Determine the day of the new date
    # If the day of the current date is at the end of the month,
    # the day of the new date should also be at the end of the month
    if(date.day == calendar.monthrange(date.year, date.month)[1]):
        day = calendar.monthrange(year, month)[1]
    else:
        day = date.day

    new_date = datetime.datetime(year, month, day)
    return new_date
它还支持添加负月份(即减去月份)

以下是一些示例用法,说明了如何根据您的规格获得2021年和2022年的日期:

import datetime

a = datetime.datetime(2020, 1, 1)

# Initialse a list to hold the dates
dates = [0]*8

# Obtain the dates
for i in range(0, len(dates)):
    dates[i] = add_months(a, 3*i)

dates

取决于你考虑一个月。总是90天吗?为什么不定个日期呢?例如,使用1月1日、4月1日、7月1日、10月1日。这满足了“一年四次”的要求,你不必选择第一天,可以是第五天或第十天,或者你选择的任何一天。唯一的缺点是第一季度有90天或91天,第二季度有91天,第三季度和第四季度都有92天,但这对政府工作来说已经足够了。仅供参考,我最终使用PostgresSQL进行了所有日期计算,因为它是迄今为止最好、最合理、最干净的计算方法。不过,我在下面标出了python的最佳答案。这是一个“足够好”的解决方案。我喜欢使用
3*365/12
而不是
3*30
。我知道
2012-06-05
你的日期设置错了吗?因为今天是3月6日。而且,这里的三个月正好是91天,除非你这样做
3*365.0/12
。然后是91天6小时。哦,是的,在我的虚拟机上测试过。谢谢。
relativedelta(month=3)
relativedelta(month=3)
有着完全不同的行为,我努力想知道我错过了“month”上的一个“s”,也许在你非常好的回答中提到这一点很好:)打得好!我更新了回复以反映您的评论,并在回复时修复了一个打字错误。:)大+1到
dateutil
module这是一个有点飘忽不定的月份,天数较少。你应该做的是
delta+delta+TODAY
,而不是
TODAY+delta+delta…
。这可以确保即使是二月,你也会在你结束月份的最佳日子着陆。如果月份不适用于
月份的负值,则不适用于
月份的负值。如果月份不适用于
月份的负值,则不适用于
月份的负值,则可以包含其用法的示例代码来解决原始问题吗?现在查看一下。增加了2021年和2022年的样本
    import datetime
    import calendar
    def add_months(dateInput, months):
        months_count = dateInput.month + months

        # Calculate the year
        year = dateInput.year + int((months_count-1) / 12)

        # Calculate the month
        month = (months_count % 12)
        if month == 0:
            month = 12

        # Calculate the day
        day = dateInput.day
        last_day_of_month = calendar.monthrange(year, month)[1]
        if day > last_day_of_month:
            day = last_day_of_month

        new_date = date(year, month, day)
        return new_date
import datetime
import calendar

def add_months(date, months):

    # Determine the month and year of the new date
    month, year = (date + relativedelta(months=months)).month, (date + relativedelta(months=months)).year

    # Determine the day of the new date
    # If the day of the current date is at the end of the month,
    # the day of the new date should also be at the end of the month
    if(date.day == calendar.monthrange(date.year, date.month)[1]):
        day = calendar.monthrange(year, month)[1]
    else:
        day = date.day

    new_date = datetime.datetime(year, month, day)
    return new_date
import datetime

a = datetime.datetime(2020, 1, 1)

# Initialse a list to hold the dates
dates = [0]*8

# Obtain the dates
for i in range(0, len(dates)):
    dates[i] = add_months(a, 3*i)

dates