exemple - python strftime example



Comment puis-je calculer la date six mois à partir de la date actuelle en utilisant le module Python datetime? (20)

J'utilise le module Python datetime. Je cherche à calculer la date 6 mois à compter de la date actuelle. Quelqu'un pourrait-il m'aider un peu?

La raison pour laquelle je veux générer une date de 6 mois à compter de la date actuelle est de produire une date de révision. Si l'utilisateur entre des données dans le système, il aura une date de révision de 6 mois à compter de la date à laquelle il a entré les données.

https://src-bin.com


Answer #1

À partir de cette réponse , voir parsedatetime . L'exemple de code suit. Plus de détails: test unitaire avec de nombreux exemples de conversion en langage naturel -> AAAA-MM-JJ , et des bogues / problèmes apparents de conversion en 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')

Le code ci-dessus génère les éléments suivants à partir d'une machine MacOSX:

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

Answer #2

étant donné que votre variable datetime est appelée 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)

Answer #3

Cette solution fonctionne correctement pour Décembre, ce qui n'est pas le cas de la plupart des réponses sur cette page. Vous devez d'abord déplacer les mois de la base 1 (Jan = 1) à la base 0 (Jan = 0) avant d'utiliser le module (%) ou la division entière (//), sinon novembre (11) plus 1 mois vous donne 12 , qui en trouvant le reste (12% 12) donne 0.

(Et ne pas suggérer "(mois% 12) + 1" ou oct + 1 = décembre!)

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)

Cependant ... Cela ne tient pas compte du problème comme le 31 janvier + un mois. Nous revenons donc à l'OP - que voulez-vous dire en ajoutant un mois? Une chose est de revenir en arrière jusqu'à une journée valide, étant donné que la plupart des gens présumeraient que le dernier jour de janvier, plus un mois, équivaudrait au dernier jour de février. Cela fonctionnera également sur des nombres négatifs de mois. Preuve:

>>> 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)>>> 

Answer #4

Donc, voici un exemple de dateutil.relativedelta que j'ai trouvé utile pour itération au cours de l'année écoulée, en sautant un mois à chaque fois jusqu'à la date actuelle:

>>> 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

Comme pour les autres réponses, vous devez comprendre ce que vous entendez par «dans six mois». Si vous voulez dire "le jour du mois d'aujourd'hui dans le mois six ans dans le futur" alors cela ferait:

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

Answer #5

Encore une autre solution - j'espère que quelqu'un va l'aimer:

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

Cette solution ne fonctionne pas pour les jours 29,30,31 pour tous les cas, donc une solution plus robuste est nécessaire (ce qui n'est plus si agréable :)):

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")

Answer #6

Fonction générale pour obtenir la date suivante après / avant x mois.

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)

Answer #7

J'ai résolu ce problème comme ceci:

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

Answer #8

J'ai trouvé cette solution bonne. (Ceci utilise l' extension python-dateutil )

from datetime import date
from dateutil.relativedelta import relativedelta

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

L'avantage de cette approche est qu'elle prend en charge les problèmes avec 28, 30, 31 jours, etc. Cela devient très utile pour gérer les règles et les scénarios métier (par exemple génération de facture, etc.)

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

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

Answer #9

J'utilise cette fonction pour changer l'année et le mois mais garder le jour:

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

Tu devrais écrire:

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)

Answer #10

Je pense qu'il serait plus sûr de faire quelque chose comme ça au lieu d'ajouter manuellement des jours:

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)

Answer #11

La classe QDate de PyQt4 a une fonction 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)

Answer #12

Modification de AddMonths () à utiliser dans Zope et gestion des numéros de jour invalides:

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)

Answer #13

Pour le début du calcul de mois en mois:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

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

Answer #14

Que dis-tu de ça? Vous n'utilisez pas une autre bibliothèque ( dateutil ) ou timedelta ? en s'appuyant sur la réponse de , je l'ai fait et je crois que ça fonctionne:

import datetime

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

J'ai essayé d'utiliser timedelta , mais parce que ça compte les jours, 365/2 ou 6*356/12 365/2 ne se traduit pas toujours par 6 mois, mais plutôt par 182 jours. par exemple

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

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

Je crois que nous supposons habituellement que 6 mois d'un certain jour se poseront le même jour du mois mais 6 mois plus tard (c.-à-d. 2015-03-10 -> 2015-09-10 , Non 2015-09-08 )

J'espère que ça t'as aidé.


Answer #15

Reprise d'une réponse antérieure par user417751. Peut-être pas si pythonique, mais il prend soin de différentes durées de mois et d'années bissextiles. Dans ce cas 31 janvier 2012 + 1 mois = 29 février 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)

Answer #16

Une autre solution: calculer la somme des jours du mois pour le mois suivant et ajouter le résultat à la date actuelle.

import calendar
import datetime

def date_from_now(months):
    today = datetime.datetime.today()

    month = today.month
    year = today.year
    sum_days = 0

    for i in range(int(months)):
        month += 1

        if month == 13:
            month = 1
            year += 1

        sum_days += calendar.monthrange(year, month)[1]

    return datetime.date.today() + datetime.timedelta(sum_days)

print(date_from_now(12)) # if to day is 2017-01-01, output: 2019-01-01 

Answer #17

Utilisez simplement la méthode timetuple pour extraire les mois, ajouter vos mois et construire un nouvel objet date. S'il existe déjà une méthode pour cela, je ne le connais pas.

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)

L'API est un peu maladroite, mais fonctionne comme un exemple. De toute évidence, ne fonctionne pas sur les cas de coin comme 2008-01-31 + 1 mois. :)


Answer #18

Voici un exemple qui permet à l'utilisateur de décider comment retourner une date où le jour est supérieur au nombre de jours du mois.

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)

Answer #19
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))

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




datetime