Как рассчитать дату через шесть месяцев с текущей даты с помощью модуля datetime Python?



Я использую модуль datetime Python. Я ищу, чтобы вычислить дату 6 месяцев от текущей даты. Может кто-нибудь помочь мне сделать это?



причина, по которой я хочу создать дату 6 месяцев с текущей даты, заключается в создании даты обзора. Если пользователь вводит данные в систему, он будет иметь дату обзора 6 месяцев с даты ввода данных.

647   30  

30 ответов:

import datetime
print (datetime.date.today() + datetime.timedelta(6*365/12)).isoformat()

Я нашел это решение, чтобы быть хорошим. (Это использует python-dateutil extension)

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

преимущество такого подхода заключается в том, что он заботится о проблемах с 28, 30, 31 день и т. д. Это становится очень полезным при обработке бизнес-правил и сценариев (например, создание счета и т. д.)

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)

Ну, это зависит от того, что вы подразумеваете под 6 месяцами с текущей даты.

  1. используя природный месяцев:

    (day, month, year) = (day, (month+6)%12, year+(month+6)/12)
    
  2. используя определение банкира, 6*30:

    date += datetime.timedelta(6*30)
    

для расчета от месяца к месяцу:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)

что вы подразумеваете под '6 месяцев'. Это 2009-02-13 + 6 месяцев == 2009-08-13 или это 2009-02-13 + 6*30 дней?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

подробнее о mx.DateTime

это решение работает правильно для декабря, что большинство ответов на этой странице не делают. Вам нужно сначала переместить месяцы из базы 1 (т. е. Jan = 1) в базу 0 (т. е. Jan = 0) перед использованием модуля ( % ) или целочисленного деления ( / / ), иначе ноябрь ( 11) плюс 1 месяц дает вам 12, что при нахождении остатка (12% 12 ) дает 0.

(и не предлагайте "(месяц % 12) + 1" или Октябрь + 1 = декабрь!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = d.year + ((( d.month - 1) + x ) / 12 ) 
    return datetime.date( newyear, newmonth, d.day)

однако ... Это не учитывает проблему, как 31 января + один месяц. Итак, мы возвращаемся к OP-что вы имеете в виду, добавив месяц? Один soln-вернуться назад, пока вы не доберетесь до действительного дня, учитывая, что большинство людей будут предполагать, что последний день января плюс один месяц равен последнему дню февраля. Это будет работать и на отрицательных числах месяцев. Доказательство:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 

нет прямого способа сделать это с помощью Python datetime.

Проверьте тип relativedelta в python-dateutil. Это позволяет указать интервал времени в месяцах.

Я знаю, что это было в течение 6 месяцев, однако ответ показывает в google для "добавления месяцев в python", если вы добавляете один месяц:

import calendar

date = datetime.date.today()    //Or your date

datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

это будет считать дни в текущем месяце и добавить их к текущей дате, используя 365/12 будет объявление 1/12 года может вызвать проблемы для коротких / длинных месяцев, если ваш итерации по дате.

Dateutil package реализация такой функциональности. Но знайте, что это будет наивный, как указал уже.

вот пример dateutil.relativedelta который я нашел полезным для итерации через прошлый год, пропуская месяц каждый раз до текущей даты:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

как и с другими ответами, вы должны выяснить, что вы на самом деле подразумеваете под "6 месяцев с этого момента."Если вы имеете в виду" сегодняшний день месяца в месяце шесть лет в будущем", то это будет делать:

datetime.datetime.now() + relativedelta(months=6)

просто использовать timetuple метод для извлечения месяцев, добавить свои месяцы и построить новый dateobject. Если есть уже существующий метод для этого я не знаю.

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), new_month % 12, day)

API немного неуклюж, но работает в качестве примера. Также, очевидно, не будет работать на угловых случаях, таких как 2008-01-31 + 1 месяц. :)

использование стандартных библиотек Python, т. е. без dateutil или другие, и решение проблемы "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))

У меня есть лучший способ решить проблему 31 февраля':

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

Я думаю, что он также работает с отрицательными числами (чтобы вычесть месяцы), но я не проверял это очень много.

класс QDate PyQt4 имеет функцию addmonths.

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)

изменен AddMonths() для использования в Zope и обработки недопустимых номеров дней:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)
import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(tuple(t)))

как насчет этого? Не используя другую библиотеку (dateutil) или timedelta? здание на vartecответ я сделал это, и я считаю, что это работает:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

я пробовал использовать timedelta, а потому что он считает дни,365/2 или 6*356/12 не всегда переводится на 6 месяцев, а скорее на 182 дня. например,

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

Я считаю, что мы обычно предполагаем, что 6 месяцев с определенного дня приземлятся в тот же день месяца, но 6 месяцев спустя (т. е. 2015-03-10 -->2015-09-10, а не 2015-09-08)

Я надеюсь, вы найдете это полезным.

Я решил эту проблему так:

import calendar
from datetime import datetime
moths2add = 6
now = datetime.now()
current_year = now.year
current_month = now.month
#count days in months you want to add using calendar module
days = sum(
  [calendar.monthrange(current_year, elem)[1] for elem in range(current_month, current_month + moths)]
    )
print now + days

модифицированный ответ Йоханнеса Вея в случае 1new_month = 121. Это прекрасно работает для меня. Месяцы могут быть положительными или отрицательными.

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)

еще одно решение-надеюсь, кому-то понравится:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

это решение не работает в течение 29,30,31 дней для всех случаев, поэтому требуется более надежное решение (что уже не так приятно:)):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")

С ответ см. parsedatetime. Ниже приведен пример кода. Более детально: модульный тест со многими примерами преобразования естественного языка- > гггг-ММ-ДД, и очевидно проблемы преобразования parsedatetime/ошибки.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

приведенный выше код генерирует следующее с компьютера MacOSX:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 

учитывая, что ваша переменная datetime называется date:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)

общая функция для получения следующей даты после / до x месяцев.

from datetime import date

def after_month(given_date, month):
    yyyy = int(((given_date.year * 12 + given_date.month) + month)/12)
    mm = int(((given_date.year * 12 + given_date.month) + month)%12)

    if mm == 0:
        yyyy -= 1
        mm = 12
    return given_date.replace(year=yyyy, month=mm)


if __name__ == "__main__":
    today = date.today()
    print(today)

    for mm in [-12, -1, 0, 1, 2, 12, 20 ]:
        next_date = after_month(today, mm)
        print(next_date)

С Python 3.X вы можете сделать это так:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

но вам нужно будет установить python-dateutil модуль:

pip install python-dateutil

используйте модуль python datetime, чтобы добавить timedelta из шести месяцев в datetime.сегодняшний день. )(

http://docs.python.org/library/datetime.html

вам, конечно, придется решить вопрос, поднятый Йоханнесом Вайсом-что do вы имеете в виду 6 месяцев?

вот что я придумал. Он перемещает правильное количество месяцев и лет, но игнорирует дни (что было мне нужно в моей ситуации).

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)

Я использую эту функцию, чтобы изменить год и месяц, но держать дня:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

вы должны написать:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)

Я думаю, что было бы безопаснее сделать что-то вроде этого, а не вручную добавлять дни:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

newdate = addMonths(today, 6)
import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __name__ == '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))

переработать более ранний ответ user417751. Может быть, не так питонский способ, но он заботится о разных длинах месяцев и високосных годах. В этом случае 31 января 2012 года + 1 месяц = 29 февраля 2012 года.

import datetime
import calendar

def add_mths(d, x):
    newday = d.day
    newmonth = (((d.month - 1) + x) % 12) + 1
    newyear  = d.year + (((d.month - 1) + x) // 12)
    if newday > calendar.mdays[newmonth]:
        newday = calendar.mdays[newmonth]
        if newyear % 4 == 0 and newmonth == 2:
            newday += 1
    return datetime.date(newyear, newmonth, newday)

Comments

    Ничего не найдено.