1

I only have datetime, timedelta and date modules in my python. Unfortunately I’ll not be able to use relativedelta to simply add months and years easily.

I would need some advice in adding months and years to a date. Have been trying but can’t think of a better way to take into account for those have >30 days, Leap year.

30days = Date.today() + timedelta(days=30)
Dformat = 30days.strftime(“%Y-%m-%d”)

Anyone has a way to add different months and years in a better way given I only have these limited modules?

1
  • So are you trying to add 30 days to lets say, jan, to get output as feb ? Commented Mar 26, 2021 at 7:00

2 Answers 2

1

I know no builtin way. But it can easily done by hand:

def add_year(dt, years):
    """
    Add years years to dt and return the new value.

    dt can be a date or datetime, years must be an integer value (may be negative)
    """
    try:
        return dt.replace(year=dt.year + years)
    except ValueError:
        # the day that does not exist in new month: return last day of month
        return dt.replace(year=dt.year + years, month=dt.month + 1, day=1
              ) - timedelta(days=1)

def add_month(dt, months):
    """
    Add months months to dt and return the new value.

    dt can be a date or datetime, months must be an integer value (may be negative)
    """
    y, m = divmod(months + dt.month, 12)
    try:
        return dt.replace(year=dt.year + y, month=m)
    except ValueError:
        # the day that does not exist in new month: return last day of month
        return dt.replace(year=dt.year + y, month=m + 1, day=1
                          ) - timedelta(days=1)

Demo:

>>> d = date(2020, 12, 10)
>>> add_month(d, 3)
datetime.date(2021, 3, 10)
>>> add_month(d, -13)
datetime.date(2019, 11, 10)

It even handles shorter months:

>>> d =date(2017,1,30)
>>> add_month(d, 1)
datetime.date(2017, 2, 28)
Sign up to request clarification or add additional context in comments.

4 Comments

note that this will fail if the initial date is Feb 29th in a leap year and you try to add a number of years that is not a multiple of 4 etc. - dateutil.relativedelta might offer a safer way to go.
@MrFuppes: You are right, I was not cautious enough on my first code. Should be better now. BTW OP explicitely declared I’ll not be able to use relativedelta.
Ok seems like I should be more cautious reading the question ^^ Actually reads like a homework assignment; "not able to use package x" sounds like "use the hard way and learn something"
Managed to figure out with relativddelta installation. But the solution works too.
0

There are a lot of different possibilities. I give you an example which take a date and return the last day of quarter but you can, obviously, apply this methodology to any frequency, So:

If you have datetime, you can have a object dt defines as a datetime.date

You can build a function get_quarter_end which take as input a datetime.date object and return the last day of quarter.

def get_quarter_end(dt):
    # dt: datetime.date
    # firts we get the year of the next quarter
    nextQtYr = dt.year + (1 if dt.month > 9 else 0)
    # then the month
    nextQtFirstMo = (dt.month - 1) // 3 * 3 + 4
    nextQtFirstMo = 1 if nextQtFirstMo == 13 else nextQtFirstMo
    # finally the day (first day of the next quarter)
    nextQtFirstDy = date(nextQtYr, nextQtFirstMo, 1)
    # so we have all information about the next quarter, because we are  
    # interested by the date at the end of the quarter, we just need to 
    # substract 1 day: 
    return nextQtFirstDy - timedelta(days=1)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.