2013-04-01 14 views
36

ho recuperato una datada banca dati con il seguente variabileaggiungere uno anno in data odierna PITONE

{{ i.operation_date }} 

con il quale ho avuto un valore come

April 1, 2013 

ho bisogno aggiungere un anno a quanto sopra, in modo che io possa ottenere

April 1, 2014 

Si prega di suggerire, come posso fare questo?

+4

[Che cosa hai provato?] (Http://mattgemmell.com/2008/12/08/what-have-you-tried/) –

+0

Se si vuole fare questo nei modelli solo, allora vedi questo http://stackoverflow.com/questions/10715253/display-timestamp-in-django-template. Ora puoi scrivere un tag modello che può aggiungere un anno al valore corrente. –

+0

correlati: [Come convertire anni in secondi] (http://stackoverflow.com/a/32658742/4279) – jfs

risposta

-1

convertirlo in oggetto datetime python se non lo è già. quindi aggiungi deltatime

one_years_later = Your_date + datetime.timedelta(days=(years*days_per_year)) 

per i giorni del tuo caso = 365.

si può avere condizioni per verificare se l'anno è bisestile o no e regolare giorni di conseguenza

è possibile aggiungere come molti anni come si desidera

+4

-1 a causa degli anni bisestili: 'data (2012, 1, 1) + timedelta (giorni = 365) '→' date (2012, 12, 31) ' –

26

È possibile utilizzare Python-dateutil'srelativedelta per incrementare un oggetto datetime pur rimanendo sensibile a cose come anni bisestili e lunghezze mensili. Python-dateutil viene fornito con matplotlib se già lo hai. È possibile effettuare le seguenti operazioni:

from dateutil.relativedelta import relativedelta 

new_date = old_date + relativedelta(years=1) 

(Questa risposta è stata data da @Max ad un similar question).

Ma se la data è una stringa (vale a dire non già un oggetto datetime) è possibile convertire utilizzando datetime:

from datetime import datetime 
from dateutil.relativedelta import relativedelta 

your_date_string = "April 1, 2012" 
format_string = "%B %d, %Y" 

datetime_object = datetime.strptime(your_date_string, format_string).date() 
new_date = datetime_object + relativedelta(years=1) 
new_date_string = datetime.strftime(new_date, format_string).replace(' 0', ' ') 

new_date_string conterrà "1 apr 2013".

NB: Sfortunatamente, datetime emette solo i valori del giorno come "numeri decimali" - cioè con zeri iniziali se si tratta di numeri a una cifra. Il .replace() alla fine è una soluzione per affrontare questo problema copiato da @Alex Martelli (vedi this question per il suo e altri approcci a questo problema).

8

Sembra dalla tua domanda che desideri semplicemente incrementare l'anno della data specificata piuttosto che preoccuparti delle implicazioni sull'anno bisestile. Puoi usare la data class per farlo accedendo al suo anno membro.

from datetime import date 
startDate = date(2012, 12, 21) 

# reconstruct date fully 
endDate = date(startDate.year + 1, startDate.month, startDate.day) 
# replace year only 
endDate = startDate.replace(startDate.year + 1) 

Se hai problemi a creare un determinato formato, faccelo sapere.

+0

Non preoccuparsi degli anni bisestili porta a un codice scadente. –

+0

@AntonyHatchkins: puoi spiegare perché il codice in questa risposta è scadente? Sembra giusto per me. –

+16

'z = datetime (2012,02,29); z.replace (z.year + 1) '->' ValueError: giorno è fuori intervallo per mese' –

72

AGSM's answer mostra un modo conveniente per risolvere questo problema utilizzando il pacchetto python-dateutil. Ma cosa succede se non vuoi installare quel pacchetto?Si potrebbe risolvere il problema in vaniglia Python come questo:

from datetime import date 

def add_years(d, years): 
    """Return a date that's `years` years after the date (or datetime) 
    object `d`. Return the same calendar date (month and day) in the 
    destination year, if it exists, otherwise use the following day 
    (thus changing February 29 to March 1). 

    """ 
    try: 
     return d.replace(year = d.year + years) 
    except ValueError: 
     return d + (date(d.year + years, 1, 1) - date(d.year, 1, 1)) 

Se si desidera che l'altra possibilità (cambiando 29 febbraio - 28 febbraio), poi l'ultima riga deve essere modificato:

 return d + (date(d.year + years, 3, 1) - date(d.year, 3, 1)) 
+28

Questa dannata funzione dovrebbe essere in Python stesso ... – PedroMorgan

+2

Corretto, spero che aggiungeranno. – WebOrCode

+2

le risposte sono diverse: 'relativedelta()' mantiene l'ultimo giorno del mese, ad esempio, 'date (2016, 2, 29) + relativedelta (years = 1) == date (2017, 2, 28)'. La tua soluzione produce (come documentato) il primo giorno del mese successivo: 'add_years (date (2016,2,29), 1) == date (2017, 3, 1)' – jfs

0

Guarda questo: utilizzo

#!/usr/bin/python 

import datetime 

def addYears(date, years): 
    result = date + datetime.timedelta(366 * years) 
    if years > 0: 
     while result.year - date.year > years or date.month < result.month or date.day < result.day: 
      result += datetime.timedelta(-1) 
    elif years < 0: 
     while result.year - date.year < years or date.month > result.month or date.day > result.day: 
      result += datetime.timedelta(1) 
    print "input: %s output: %s" % (date, result) 
    return result 

Esempio:

addYears(datetime.date(2012,1,1), -1) 
addYears(datetime.date(2012,1,1), 0) 
addYears(datetime.date(2012,1,1), 1) 
addYears(datetime.date(2012,1,1), -10) 
addYears(datetime.date(2012,1,1), 0) 
addYears(datetime.date(2012,1,1), 10) 

e l'output di questo esempio:

input: 2012-01-01 output: 2011-01-01 
input: 2012-01-01 output: 2012-01-01 
input: 2012-01-01 output: 2013-01-01 
input: 2012-01-01 output: 2002-01-01 
input: 2012-01-01 output: 2012-01-01 
input: 2012-01-01 output: 2022-01-01 
0

Questo è quello che faccio quando ho bisogno di aggiungere mesi o anni e non voglio importare più librerie. Basta creare un oggetto datetime.date(), chiamare add_month (data) per aggiungere un mese e add_year (data) per aggiungere un anno.

import datetime 
__author__ = 'Daniel Margarido' 


# Check if the int given year is a leap year 
# return true if leap year or false otherwise 
def is_leap_year(year): 
    if (year % 4) == 0: 
     if (year % 100) == 0: 
      if (year % 400) == 0: 
       return True 
      else: 
       return False 
     else: 
      return True 
    else: 
     return False 


THIRTY_DAYS_MONTHS = [4, 6, 9, 11] 
THIRTYONE_DAYS_MONTHS = [1, 3, 5, 7, 8, 10, 12] 

# Inputs -> month, year Booth integers 
# Return the number of days of the given month 
def get_month_days(month, year): 
    if month in THIRTY_DAYS_MONTHS: # April, June, September, November 
     return 30 
    elif month in THIRTYONE_DAYS_MONTHS: # January, March, May, July, August, October, December 
     return 31 
    else: # February 
     if is_leap_year(year): 
      return 29 
     else: 
      return 28 

# Checks the month of the given date 
# Selects the number of days it needs to add one month 
# return the date with one month added 
def add_month(date): 
    current_month_days = get_month_days(date.month, date.year) 
    next_month_days = get_month_days(date.month + 1, date.year) 

    delta = datetime.timedelta(days=current_month_days) 
    if date.day > next_month_days: 
     delta = delta - datetime.timedelta(days=(date.day - next_month_days) - 1) 

    return date + delta 


def add_year(date): 
    if is_leap_year(date.year): 
     delta = datetime.timedelta(days=366) 
    else: 
     delta = datetime.timedelta(days=365) 

    return date + delta 


# Validates if the expected_value is equal to the given value 
def test_equal(expected_value, value): 
    if expected_value == value: 
     print "Test Passed" 
     return True 

    print "Test Failed : " + str(expected_value) + " is not equal to " str(value) 
    return False 

# Test leap year 
print "---------- Test leap year ----------" 
test_equal(True, is_leap_year(2012)) 
test_equal(True, is_leap_year(2000)) 
test_equal(False, is_leap_year(1900)) 
test_equal(False, is_leap_year(2002)) 
test_equal(False, is_leap_year(2100)) 
test_equal(True, is_leap_year(2400)) 
test_equal(True, is_leap_year(2016)) 

# Test add month 
print "---------- Test add month ----------" 
test_equal(datetime.date(2016, 2, 1), add_month(datetime.date(2016, 1, 1))) 
test_equal(datetime.date(2016, 6, 16), add_month(datetime.date(2016, 5, 16))) 
test_equal(datetime.date(2016, 3, 15), add_month(datetime.date(2016, 2, 15))) 
test_equal(datetime.date(2017, 1, 12), add_month(datetime.date(2016, 12, 12))) 
test_equal(datetime.date(2016, 3, 1), add_month(datetime.date(2016, 1, 31))) 
test_equal(datetime.date(2015, 3, 1), add_month(datetime.date(2015, 1, 31))) 
test_equal(datetime.date(2016, 3, 1), add_month(datetime.date(2016, 1, 30))) 
test_equal(datetime.date(2016, 4, 30), add_month(datetime.date(2016, 3, 30))) 
test_equal(datetime.date(2016, 5, 1), add_month(datetime.date(2016, 3, 31))) 

# Test add year 
print "---------- Test add year ----------" 
test_equal(datetime.date(2016, 2, 2), add_year(datetime.date(2015, 2, 2))) 
test_equal(datetime.date(2001, 2, 2), add_year(datetime.date(2000, 2, 2))) 
test_equal(datetime.date(2100, 2, 2), add_year(datetime.date(2099, 2, 2))) 
test_equal(datetime.date(2101, 2, 2), add_year(datetime.date(2100, 2, 2))) 
test_equal(datetime.date(2401, 2, 2), add_year(datetime.date(2400, 2, 2))) 
Problemi correlati