0

Adding days to any date and even February and leap year too if any.

Here is the date i have : 2020-07-08T07:03:08Z

I need to add days to the above date with some if else conditions.

if(month):
    # i need to increment 30/31 days as per the month have 
    next_upcoming_date = 2020-08-07T07:03:08Z
if(year):
    # i need to increment 365/366(when leap year) as per the year 
    next_upcoming_date = 2021-07-07T07:03:08Z

Example: if 31st If the subscription terms are $25.99 USD a month and the subscriber signs up on Thursday, July 31. The subscriber is billed as follows:

Thursday, July 31 = $25.99 USD
Saturday, August 31 = $25.99 USD
Wednesday, October 1= $25.99 USD
Saturday, November 1= $25.99 USD
and so on

Example: if 30th If the subscription terms are $25.99 USD a month and the subscriber signs up on Tuesday, December 30, the subscriber is billed as follows:

Tuesday, December 30 = $25.99 USD
Friday, January 30 = $25.99 USD
Sunday, March 1= $25.99 USD
Wednesday, April 1= $25.99USD
and so on

please Suggest me how can i achieve this.

Anonymous
  • 23
  • 1
  • 8
  • Are you aware of `timedelta` within the `datetime` module? You can simply say add timedeltas to a date – h0r53 Jul 01 '20 at 14:05
  • Am sorry.. am new bie :(. please forgive – Anonymous Jul 01 '20 at 14:05
  • Could you provide a bit more code so we can see a larger scope of what you've done already? It isn't very clear what you're trying to do. – h0r53 Jul 01 '20 at 14:06
  • 1
    related: https://stackoverflow.com/questions/546321/how-do-i-calculate-the-date-six-months-from-the-current-date-using-the-datetime – FObersteiner Jul 01 '20 at 14:21
  • What is the *goal* for the new date? Are you just trying to add one month or one year and account for differing number of days in the months? You should probably add some more examples of starting dates and desired results. – wwii Jul 01 '20 at 14:34
  • When you *add a month* do you want the new date to be the same number of days from the beginning as the original was? Or the same minus one day? ... Regardless of the month if the original is day 8 the new is day 7? – wwii Jul 01 '20 at 14:50
  • Here is a similar Q&A regarding determining months based on a strict legal definition. It may not meet your exact requirements but the answers may point you to a couple of strategies. [Measuring months between two dates : legislative definition of months](https://stackoverflow.com/questions/60626634/measuring-months-between-two-dates-legislative-definition-of-months) – wwii Jul 01 '20 at 14:57

3 Answers3

2

the dateutil package offers a convenient way to do this:

from datetime import datetime
from dateutil.relativedelta import relativedelta

# convert string to datetime object:
s = '2020-07-08T07:03:08Z'
dt = datetime.fromisoformat(s.replace('Z', '+00:00'))
# datetime.datetime(2020, 7, 8, 7, 3, 8, tzinfo=datetime.timezone.utc)

# add a month:
dt_plus_month = dt + relativedelta(months=1)
# datetime.datetime(2020, 8, 8, 7, 3, 8, tzinfo=datetime.timezone.utc)

dt_plus_year = dt + relativedelta(years=1)
# datetime.datetime(2021, 7, 8, 7, 3, 8, tzinfo=datetime.timezone.utc)
FObersteiner
  • 22,500
  • 8
  • 42
  • 72
  • This relativedelta Library will take care of Leap year as well? – Anonymous Jul 01 '20 at 14:26
  • @Anonymous: yes, check [this page](https://dateutil.readthedocs.io/en/stable/relativedelta.html) of the documentation. – FObersteiner Jul 01 '20 at 14:30
  • 1
    Will implement this and will approve :) – Anonymous Jul 01 '20 at 14:31
  • for this date s = '2020-01-31T07:03:08Z' and aam getting o/p as 2020-02-29 07:03:08+00:00 --> month. But i want 1 march. when "s" falls on the 31st, date should be 1st of the month. If the initial date falls on the 29th or 30th, it should be 1st of the month on the following February. – Anonymous Jul 02 '20 at 04:57
  • Please suggest me how to achieve this – Anonymous Jul 02 '20 at 05:00
  • @Anonymous: to clarify - if your initial date is the end of a month, you want to add 1 month and 1 day? – FObersteiner Jul 02 '20 at 05:14
  • a month and the subscriber signs up on Tuesday, December 30, the subscriber is billed as follows: **Tuesday, December 30 = $25.99 USD Friday, January 30 = $25.99 USD Sunday, March 1= $25.99 USD Wednesday, April 1= $25.99USD and so on** – Anonymous Jul 02 '20 at 05:15
  • @Anonymous: I still don't get it ;-) you mean business month? – FObersteiner Jul 02 '20 at 05:27
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/217060/discussion-between-anonymous-and-mrfuppes). – Anonymous Jul 02 '20 at 05:30
  • Updated my question – Anonymous Jul 02 '20 at 05:39
  • Ex: on the 31st If the subscription terms are $25.99 USD a month and the subscriber signs up on Thursday, July 31. The subscriber is billed as follows: Thursday, July 31 = $25.99 USD Saturday, August 31 = $25.99 USD Wednesday, October 1= $25.99 USD Saturday, November 1= $25.99 USD and so on Ex: on the 30th If the subscription terms are $25.99 USD a month and the subscriber signs up on Tuesday, December 30, the subscriber is billed as follows: Tuesday, December 30 = $25.99 USD Friday, January 30 = $25.99 USD Sunday, March 1= $25.99 USD Wednesday, April 1= $25.99USD and so on – Anonymous Jul 02 '20 at 06:25
0

for the year you could do

from re import split

a="2020-08-07T07:03:08Z"
parsed = split("-", a)

if (parsed[0] % 4) == 0:
       print("Leap Year!")
else:
       print("Not Leap Year ):.")

maybe a bit complicated but it's pure python

for the month you could do:

from re import split

a="2020-08-07T07:03:08Z"
parsed = split("-", a)
if parsed[1] in [01, 03, 05, 07, 08, 10, 12]:
           print("31 month!")
else:
           print("30 month ): .")
chboo1
  • 63
  • 9
0

here's a suggestion how to get the desired output, after OP's update of the question. It is significantly different from the original version, so I decided to make it a new answer.

from datetime import datetime
from calendar import monthrange
from dateutil.relativedelta import relativedelta

s = '2020-07-31T07:03:08Z'
dt = datetime.fromisoformat(s.replace('Z', '+00:00'))

for _ in range(6):
    print(dt)
    # first, add a month
    dt += relativedelta(months=1)
    # then analyse the result if it falls on a month with less than 31 days:
    mr = monthrange(dt.year, dt.month)
    if mr[1] < 31 and dt.day != 1: # also check if day==1, leave it at that if so.
        dt += relativedelta(days=1)
    
# 2020-07-31 07:03:08+00:00
# 2020-08-31 07:03:08+00:00
# 2020-10-01 07:03:08+00:00
# 2020-11-01 07:03:08+00:00
# 2020-12-01 07:03:08+00:00
# 2021-01-01 07:03:08+00:00


s = '2020-12-30T07:03:08Z'
dt = datetime.fromisoformat(s.replace('Z', '+00:00'))

for _ in range(6):
    print(dt)
    dt += relativedelta(months=1)
    mr = monthrange(dt.year, dt.month)
    if mr[1] < 31 and dt.day != 1:
        dt += relativedelta(days=1)
        
# 2020-12-30 07:03:08+00:00
# 2021-01-30 07:03:08+00:00
# 2021-03-01 07:03:08+00:00
# 2021-04-01 07:03:08+00:00
# 2021-05-01 07:03:08+00:00
# 2021-06-01 07:03:08+00:00
FObersteiner
  • 22,500
  • 8
  • 42
  • 72