Add one year in current date PYTHON
Asked Answered
E

11

102

I have fetched a date from database with the following variable

{{ i.operation_date }}

with which I got a value like

April 1, 2013

I need to add one year to the above, so that I can get

April 1, 2014

Please suggest, how can I do this?

Enslave answered 1/4, 2013 at 10:19 Comment(1)
If you want to do this in the templates only, then see this #10715753. You can now write a template tag that can add one year to the current value.Beliabelial
D
135

AGSM's answer shows a convenient way of solving this problem using the python-dateutil package. But what if you don't want to install that package? You could solve the problem in vanilla Python like this:

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

If you want the other possibility (changing February 29 to February 28) then the last line should be changed to:

        return d + (date(d.year + years, 3, 1) - date(d.year, 3, 1))
Disbursement answered 1/4, 2013 at 12:56 Comment(4)
Correct, I hope they will add.Usurious
the answers are different: relativedelta() keeps the last of day of the month i.e., date(2016, 2, 29) + relativedelta(years=1) == date(2017, 2, 28). Your solution yields (as documented) the first day of the next month: add_years(date(2016,2,29), 1) == date(2017, 3, 1)Elephus
How about changing the last line to: return date(d.year + years, 3, 1). Much easier to read that way.Groceries
How to use this?Effable
F
125

You can use Python-dateutil's relativedelta to increment a datetime object while remaining sensitive to things like leap years and month lengths. Python-dateutil comes packaged with matplotlib if you already have that. You can do the following:

from dateutil.relativedelta import relativedelta

new_date = old_date + relativedelta(years=1)

(This answer was given by @Max to a similar question).

But if your date is a string (i.e. not already a datetime object) you can convert it using 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 will contain "April 1, 2013".

NB: Unfortunately, datetime only outputs day values as "decimal numbers" - i.e. with leading zeros if they're single digit numbers. The .replace() at the end is a workaround to deal with this issue copied from @Alex Martelli (see this question for his and other approaches to this problem).

Frequentative answered 1/4, 2013 at 11:37 Comment(1)
The only issue I know about when adding whole years to a date is to do with leap years and Feb 29. Saying "things" in the plural and mentioning "month lengths" in the plural as well as if it's something additional to leap years is misleading. I believe as long as you account for Feb 29 in leap years the job is done. There is a question about what you mean by a year: either a fixed length of time such as 365.25 days for instance, or if you just mean "the same date on the subsequent year", but that's a different question, not a different problem in the solution space.Miran
D
16

It seems from your question that you would like to simply increment the year of your given date rather than worry about leap year implications. You can use the date class to do this by accessing its member year.

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)

If you're having problems creating one given your format, let us know.

Dumbfound answered 1/4, 2013 at 11:58 Comment(3)
@AntonyHatchkins: can you explain why the code in this answer is poor? It looks right to me.Disbursement
z = datetime(2012,02,29); z.replace(z.year+1) -> ValueError: day is out of range for monthFarouche
while z + relativedelta(years=1) -> datetime.datetime(2013, 2, 28, 0, 0)Farouche
S
13

You can replace the year in a date and get the expected result

import datetime
date_now = datetime.date.today()
years_to_add = date_now.year + 1

date_1 = date_now.strftime('%Y-%m-%d')
date_2 = date_now.replace(year=years_to_add).strftime('%Y-%m-%d')

print(date_1)
print(date_2)

# 2021-08-03
# 2022-08-03
Septa answered 3/8, 2021 at 19:39 Comment(1)
There's already a lot of good answers, not sure if this one really adds anything to the question.Impersonality
T
7

Another way would be to use pandas "DateOffset" class

link:-https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.tseries.offsets.DateOffset.html

Using ASGM's code(above in the answers):

from datetime import datetime
import pandas as pd

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 + pd.DateOffset(years=1)

new_date.date()

It will return the datetime object with the added year.

Something like this:-

datetime.date(2013, 4, 1)
Td answered 8/5, 2019 at 13:26 Comment(0)
B
7

Here's one more answer that I've found to be pretty concise and doesn't use external packages:

import datetime as dt
import calendar

# Today, in `dt.date` type
day = dt.datetime.now().date()

one_year_delta = dt.timedelta(days=366 if ((day.month >= 3 and calendar.isleap(day.year+1)) or
                                            (day.month < 3 and calendar.isleap(day.year))) else 365)

# Add one year to the current date
print(day + one_year_delta)
Bibliolatry answered 16/9, 2020 at 20:26 Comment(0)
D
5

This is what I do when I need to add months or years and don't want to import more libraries. Just create a datetime.date() object, call add_month(date) to add a month and add_year(date) to add a year.

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)))
Drooff answered 16/1, 2016 at 20:11 Comment(2)
add_year does not work well if it's a lap year and your date is on March or afterwards. In other words, this test fails: test_equal(datetime.date(2021, 4, 2), add_year(datetime.date(2020, 4, 2)))Unanswerable
Also: the year before a lap year will fail too: this test also fails: test_equal(datetime.date(2020, 4, 2), add_year(datetime.date(2019, 4, 2)))Unanswerable
S
1

The simplest way would be to use dateutil.relativedelta as mentioned in another answer. However, if you don't want to add an extra dependency on python-dateutil, you can implement a similar logic using only standard library modules:

from calendar import isleap
from datetime import date


def add_years(d: date, years: int):
    """Add years to a date."""
    year = d.year + years
    # if leap day and the new year is not leap, replace year and day
    # otherwise, only replace year
    if d.month == 2 and d.day == 29 and not isleap(year):
        return d.replace(year=year, day=28)
    return d.replace(year=year)


print(add_years(date(2023, 10, 26), 1))  # 2024-10-26
print(add_years(date(2000, 2, 29), 4))   # 2004-02-29
print(add_years(date(2000, 2, 29), 1))   # 2001-02-28
Slaver answered 26/10, 2023 at 9:54 Comment(0)
R
0

Look at this:

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

Example usage:

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)

And output of this example:

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
Reinaldo answered 8/5, 2015 at 11:11 Comment(0)
S
-2

convert it into python datetime object if it isn't already. then add deltatime

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

for your case days=365.

you can have condition to check if the year is leap or no and adjust days accordingly

you can add as many years as you want

Seclude answered 1/4, 2013 at 10:32 Comment(1)
−1 because of leap years: date(2012, 1, 1) + timedelta(days=365)date(2012, 12, 31)Disbursement
G
-2

Try this:

from datetime import datetime,timedelta

first=input() 

second=int(input()) 

delta = timedelta(days=second*365)

format = "%b %d %Y"

datetime_str = datetime.strptime(first, format)

print(datetime_str+delta)
Glim answered 17/12, 2022 at 5:41 Comment(1)
Do not post an answer with merely codes. While your solution can be useful, you should also explain why the code will fix the problem that was described in the question.Vanhoose

© 2022 - 2024 — McMap. All rights reserved.