2013-04-01 9 views
36

Mam pobrane datę z bazie z następujących zmiennejDodaj rok w dacie aktualnej PYTHON

{{ i.operation_date }} 

z którą dostałam wartość jak

April 1, 2013 

muszę dodać rok do powyższego, aby uzyskać

April 1, 2014 

Proszę zasugerować, jak mogę to zrobić?

+4

[Co próbowałeś?] (Http://mattgemmell.com/2008/12/08/what-have-you-tried/) –

+0

Jeśli chcesz to zrobić tylko w szablonach, a następnie zobacz ten http://stackoverflow.com/questions/10715253/display-timestamp-in-django-template. Teraz możesz napisać znacznik szablonu, który może dodać rok do bieżącej wartości. –

+0

związanych: [Jak przekonwertować lat na sekundę] (http://stackoverflow.com/a/32658742/4279) – jfs

Odpowiedz

-1

przekonwertować go na obiekt datetime Pythona, jeśli jeszcze nie jest. następnie dodaj deltatime

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

dla twoich przypadków = 365.

można mieć kondycję, aby sprawdzić, czy rok jest przestępny lub nie i ustawić dzień odpowiednio

można dodać tyle lat, ile chcesz

+4

-1 ze względu na lata przestępne: 'date (2012, 1, 1) + timedelta (dni = 365) '→' date (2012, 12, 31) ' –

26

Można użyć Python-dateutil'srelativedelta do zwiększania datetime obiekt pozostając wrażliwe na takie rzeczy jak lata przestępne i długości miesięcy. Python-dateutil jest dostarczany z matplotlib, jeśli już to masz. Można wykonać następujące czynności:

from dateutil.relativedelta import relativedelta 

new_date = old_date + relativedelta(years=1) 

(Ta odpowiedź została przyznana przez @Max do similar question).

Ale jeśli data jest ciągiem znaków (czyli nie już datetime obiektu) można przekonwertować go za pomocą 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 będzie zawierać „1 kwietnia 2013 r.”

NB: Niestety, datetime podaje tylko wartości dzienne jako "liczby dziesiętne" - tj. Z zerami wiodącymi, jeśli są to liczby jednocyfrowe. Na końcu .replace() jest obejściem tego problemu skopiowanego z @Alex Martelli (patrz: this question dla jego i innych podejść do tego problemu).

8

Z twojego pytania wynika, że ​​chciałbyś po prostu zwiększyć rok swojej daty, zamiast martwić się o konsekwencje zeszłoroczne. Możesz użyć klasy daty, aby to zrobić, uzyskując dostęp do jej roku członkowskiego.

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) 

Jeśli masz problemy z utworzeniem jednego z podanych formatów, daj nam znać.

+0

Nie martwienie się o lata przestępne prowadzi do kiepskiego kodu. –

+0

@AntonyHatchkins: czy możesz wyjaśnić, dlaczego kod w tej odpowiedzi jest słaby? Wydaje mi się to właściwe. –

+16

'z = datetime (2012,02,29); z.replace (z.year + 1) '->' ValueError: day is out of range for month' –

72

AGSM's answer przedstawia wygodny sposób rozwiązania tego problemu za pomocą pakietu python-dateutil. Ale co, jeśli nie chcesz zainstalować tej paczki?Można rozwiązać ten problem w waniliowym Pythonie tak:

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

Jeśli chcesz Druga możliwość (zmieniającą się 29 lutego do 28 lutego), a następnie ostatni wiersz powinien być zmieniony na:

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

Ta cholerna funkcja powinna być w samym pytonie ... – PedroMorgan

+2

Prawidłowo, mam nadzieję, że dodadzą. – WebOrCode

+2

odpowiedzi są różne: 'relativedelta()' zachowuje ostatni dzień miesiąca, tj. 'Date (2016, 2, 29) + relativedelta (years = 1) == date (2017, 2, 28)'. Twoje rozwiązanie daje (jak dokumentowano) pierwszy dzień następnego miesiąca: 'add_years (data (2016,2,29), 1) == data (2017, 3, 1)' – jfs

0

Spójrz na następująco:

#!/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 

Przykład użycia:

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) 

i wyjście z tego przykładu:

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

To, co robię, kiedy muszę dodać kilka miesięcy lub lat i nie chcą importować więcej bibliotek. Wystarczy utworzyć obiekt datetime.date(), wywołać add_month (data), aby dodać miesiąc i add_year (data), aby dodać rok.

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))) 
Powiązane problemy