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.
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)
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 ): .")
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
Related
Here is the problem:
If the int values [0,7) (0, 1, 2, 3, 4, 5, 6) refer to Monday through
Sunday, and today is Monday, what day of the week will it be in 999
days?
Here is how I solved it:
import datetime
#Capture the First Date
day1 = datetime.date(2021, 1, 25)
print('day1:', day1.ctime())
# Capture the Second Date
day2 = datetime.date(2023, 10, 21)
print('day2:', day2.ctime())
# Find the difference between the dates
print('Number of Days:', day1-day2)
Returns:
day1: Mon Jan 25 00:00:00 2021
day2: Sat Oct 21 00:00:00 2023
Number of Days: -999 days, 0:00:00
Use timedelta to add n days from your "start date":
from datetime import date, timedelta
current = date.today()
future = current + timedelta(days=999)
print(f"{current=}", current.weekday(), current.strftime("%A"))
print(f"{future=}", future.weekday(), future.strftime("%A"))
Output:
current=datetime.date(2021, 1, 24) 6 Sunday
future=datetime.date(2023, 10, 20) 4 Friday
.weekday() returns the day of the week as an integer.
.strftime("%A") will format a date object as a Weekday name.
I need help to make a code, that counts every 15 min of a day. Then I want the dates and time to be put in a list. The code needs to stop counting on Friday at 07.30 pm and then start again Monday 00:00 am.
this is what have so far
import datetime
dt = datetime.datetime(2008, 8, 15, 00, 00, 00, 00)
tdelta = date.timedelta(min=15)
#date2 = date1 + timedelta
#timedelta = date1 + date2
#if day is between monday 00 and friday 19:30:
#lst.append(day)
#day = day + 15
i want the result to be like this...
friday 01.05.2016 19:00pm friday 01.05.2016 19:15pm friday 01.05.2016
19:30pm friday 01.05.2016 19:45pm friday 01.05.2016 20:00pm Monday
04.05.2016 00:00am Monday 04.05.2016 00:15am Monday 04.05.2016 00:30am etc...
I am stuck at this one, hope you can help
You need smth like this:
import datetime
dt = datetime.datetime(2008, 8, 15, 00, 00, 00, 00)
tdelta = datetime.timedelta(minutes=15)
result = []
for i in range(20):
dt += tdelta
if (dt.isoweekday() < 5) or ((dt.isoweekday() == 5) and (dt.time() < datetime.datetime.strptime('19:30:00', '%H:%M:%S').time())):
result.append(dt)
print result
Below codes gives a list of dates between dateFrom to DateTo with a specific minutes range;
function (dateFrom, dateTo, minutes){
let dates = [];
let tempDate = dateFrom;
while ( tempDate < dateTo){
dates.push(tempDate);
tempDate = tempDate.setMinutes(tempDate.getMinutes() + minutes);
}
return dates;
}
I am writing code to take data from the last year. I want to round up the earlier date like so: If it is July 14 2015, I want data from August 1st 2014-July 14,2015
df = pd.read_csv('MyData.csv')
df['recvd_dttm'] = pd.to_datetime(df['recvd_dttm'])
range_max = datetime.datetime.now()
range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)
if datetime.datetime.now() == is_month_end:
# take slice with final week of data
df = df[(df['recvd_dttm'] >= range_min) &
(df['recvd_dttm'] <= range_max)]
My problem is that when it is July 31, 2015, my code goes to the end of the next month, essentially cutting out an entire month.
I am trying to make a for loop to fix this problem.
If it is the end of the month:
range_min = range_max - pd.tseries.offsets.DateOffset(years=1)
else:
range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)
How do I tell python to check for the end of the month? MonthEnd is only an offset function.
We can avoid importing the calendar module with a short function that only leverages datetime.
If tomorrow's month is not the same as today's month, then that means today is the last day of the current month. We can check this programmatically with a short function such as
import datetime
def end_of_month(dt):
todays_month = dt.month
tomorrows_month = (dt + datetime.timedelta(days=1)).month
return tomorrows_month != todays_month
Now, for your specific use case:
now = datetime.datetime.now()
if end_of_month(now):
range_min = range_max - pd.tseries.offsets.DateOffset(years=1)
else:
range_min = range_max - pd.tseries.offsets.DateOffset(years=1) +pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)
I simply would use the monthrange method of calendar module to find last day number of the month:
def check_if_last_day_of_week(date):
import datetime
import calendar
# calendar.monthrange return a tuple (weekday of first day of the
# month, number
# of days in month)
last_day_of_month = calendar.monthrange(date.year, date.month)[1]
# here i check if date is last day of month
if date == datetime.date(date.year, date.month, last_day_of_month):
return True
return False
>>> date = datetime.date(2018, 12, 31)
>>> check_if_last_day_of_week(date)
True
If the next day is a different month, it means it is the last day of a month.
def check_if_last_day_of_month(to_date):
delta = datetime.timedelta(days=1)
next_day = to_date + delta
if to_date.month != next_day.month:
return True
return False
I was using Pandas and I did not want to include another library, so I used this to check whether is the last day of the month and last day of the year:
import pandas as pd
my_date = '31-12-2021'
current_data = pd.to_datetime(my_date, format='%d-%m-%Y')
current_month = current_data.month
current_year = current_data.year
following_day = current_data + pd.DateOffset(1)
tomorrows_month = following_day.month
tomorrows_year = following_day.year
is_last_day_of_month = True if tomorrows_month != current_month else False
is_last_day_of_year = True if tomorrows_year != current_year else False
Here's a pure python approach that also takes into account leap years for february:
# total days in every month during non leap years
M_DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
def isleap(year):
"""Return True for leap years, False for non-leap years."""
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
def days_in_month(year, month):
"""Returns total number of days in a month accounting for leap years."""
return M_DAYS[month] + (month == 2 and isleap(year))
def is_monthend(ref_date):
"""Checks whether a date is also a monthend"""
return ref_date.day == days_in_month(ref_date.year, ref_date.month)
Alright, here's what I did. Found the calendar module that BryanOakley suggested and made this loop. It checks the current day and checks if it is the same as the last day of the month, and chooses the range_min accordingly.
if datetime.datetime.now().day == calendar.monthrange(date.year, date.month)[1]:
range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.DateOffset(days=1)
else:
range_min = range_max - pd.tseries.offsets.DateOffset(years=1)+ pd.tseries.offsets.MonthEnd(1) + pd.tseries.offsets.DateOffset(days=1)
import datetime
def find_curr_month_end_date(curr_date):
if(curr_date.month != 12):
next_month_first_date= curr_date.replace(day=1).replace(month=curr_date.month+1)
else:
next_month_first_date= curr_date.replace(day=1).replace(month=1).replace(year=curr_date.year+1)
curr_month_end_date = next_month_first_date - datetime.timedelta(days=1)
return curr_month_end_date
curr_date = datetime.datetime.today()
# or curr_date = datetime.datetime.strptime("2020-12-16","%Y-%m-%d")
curr_month_end_date =
find_curr_month_end_date(curr_date)
Here is a short function to accomplish this. It requires the dateutil module so that you can do relative date math.
import datetime
from dateutil.relativedelta import relativedelta
def lastyear_period_start(current_date):
last_year = current_date - relativedelta(months=11)
return datetime.date(last_year.year, last_year.month, 1)
It can be utilized like so:
dates = [
datetime.datetime(2010, 2, 27),
datetime.datetime(2011, 2, 27),
datetime.datetime(2012, 2, 27),
datetime.datetime(2013, 2, 27),
datetime.datetime(2014, 2, 27),
datetime.datetime(2010, 7, 27),
datetime.datetime(2011, 7, 27),
datetime.datetime(2012, 7, 27),
datetime.datetime(2013, 7, 27),
datetime.datetime(2014, 7, 27),
datetime.datetime(2015, 7, 14),
datetime.datetime(2015, 7, 31),
datetime.datetime(2011, 2, 28),
datetime.datetime(2012, 2, 29),
datetime.datetime(2013, 2, 28),
]
for d in dates:
print d, lastyear_period_start(d)
This prints that following
2010-02-27 00:00:00 2009-03-01
2011-02-27 00:00:00 2010-03-01
2012-02-27 00:00:00 2011-03-01
2013-02-27 00:00:00 2012-03-01
2014-02-27 00:00:00 2013-03-01
2010-07-27 00:00:00 2009-08-01
2011-07-27 00:00:00 2010-08-01
2012-07-27 00:00:00 2011-08-01
2013-07-27 00:00:00 2012-08-01
2014-07-27 00:00:00 2013-08-01
2015-07-14 00:00:00 2014-08-01
2015-07-31 00:00:00 2014-08-01
2011-02-28 00:00:00 2010-03-01
2012-02-29 00:00:00 2011-03-01
2013-02-28 00:00:00 2012-03-01
In the function we're doing two simple steps
last_year = current_date - relativedelta(months=11)
First we find out what the date was 11 months ago, based on the date passed to the function
return datetime.date(last_year.year, last_year.month, 1)
Then we return the first day of that month.
In the output above you can see this accounts for leap years as well.
I think everyone kwows when it's pi-Day (If you don't know it's on 14 March each year). When you have a result in python like:
(2016, 4, 4)
(This stands for the April 4, 2016). How can I find in a fast way when it's the next pi-Day. In this example the answer would be:
(2017, 3, 14)
Is there any formula I can use? Many thanks!
Using the datetime module you'd:
Get todays date
Get this years Pi-day (take the year from today's date)
If this date is in the past, add one year
In code:
from datetime import date
def next_pi_date():
today = date.today()
pi_date = date(today.year, 3, 14)
if pi_date < today:
pi_date = pi_date.replace(year=pi_date.year + 1)
return pi_date
Demo:
>>> from datetime import date
>>> def next_pi_date():
... today = date.today()
... pi_date = date(today.year, 3, 14)
... if pi_date < today:
... pi_date = pi_date.replace(year=pi_date.year + 1)
... return pi_date
...
>>> next_pi_date()
datetime.date(2015, 3, 14)
import datetime
dates = [
datetime.datetime(2014,2,4),
datetime.datetime(2014,3,4),
datetime.datetime(2014,3,27),
datetime.datetime(2014,4,4),
]
for d in dates:
if d.month < 3:
print datetime.datetime(d.year, 3, 14)
elif d.month == 3 and d.day <= 14:
print datetime.datetime(d.year, 3, 14)
else:
print datetime.datetime(d.year+1, 3, 14)
Outputs:
2014-03-14 00:00:00
2014-03-14 00:00:00
2015-03-14 00:00:00
2015-03-14 00:00:00
This is checking that the month is less than 3 (March) and if it is, prints this year's Pi Day. If it is March, it makes sure it's less than the 14th. If it's after March, it uses next March 14th.
Given a particular date, say 2011-07-02, how can I find the date of the next Monday (or any weekday day for that matter) after that date?
import datetime
def next_weekday(d, weekday):
days_ahead = weekday - d.weekday()
if days_ahead <= 0: # Target day already happened this week
days_ahead += 7
return d + datetime.timedelta(days_ahead)
d = datetime.date(2011, 7, 2)
next_monday = next_weekday(d, 0) # 0 = Monday, 1=Tuesday, 2=Wednesday...
print(next_monday)
Here's a succinct and generic alternative to the slightly weighty answers above.
def onDay(date, day):
"""
Returns the date of the next given weekday after
the given date. For example, the date of next Monday.
NB: if it IS the day we're looking for, this returns 0.
consider then doing onDay(foo, day + 1).
"""
days = (day - date.weekday() + 7) % 7
return date + datetime.timedelta(days=days)
Try
>>> dt = datetime(2011, 7, 2)
>>> dt + timedelta(days=(7 - dt.weekday()))
datetime.datetime(2011, 7, 4, 0, 0)
using, that the next monday is 7 days after the a monday, 6 days after a tuesday, and so on, and also using, that Python's datetime type reports monday as 0, ..., sunday as 6.
This is example of calculations within ring mod 7.
import datetime
def next_day(given_date, weekday):
day_shift = (weekday - given_date.weekday()) % 7
return given_date + datetime.timedelta(days=day_shift)
now = datetime.date(2018, 4, 15) # sunday
names = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday',
'saturday', 'sunday']
for weekday in range(7):
print(names[weekday], next_day(now, weekday))
will print:
monday 2018-04-16
tuesday 2018-04-17
wednesday 2018-04-18
thursday 2018-04-19
friday 2018-04-20
saturday 2018-04-21
sunday 2018-04-15
As you see it's correctly give you next monday, tuesday, wednesday, thursday friday and saturday. And it also understood that 2018-04-15 is a sunday and returned current sunday instead of next one.
I'm sure you'll find this answer extremely helpful after 7 years ;-)
Another alternative uses rrule
from dateutil.rrule import rrule, WEEKLY, MO
from datetime import date
next_monday = rrule(freq=WEEKLY, dtstart=date.today(), byweekday=MO, count=1)[0]
rrule docs: https://dateutil.readthedocs.io/en/stable/rrule.html
Another simple elegant solution is to use pandas offsets.
I find it very helpful and robust when playing with dates.
If you want the first Sunday just modify the frequency to freq='W-SUN'.
If you want a couple of next Sundays, change the offsets.Day(days).
Using pandas offsets allow you to ignore holidays, work only with Business Days and more.
You can also apply this method easily on a whole DataFrame using the apply method.
import pandas as pd
import datetime
# 1. Getting the closest monday from a given date
date = datetime.date(2011, 7, 2)
closest_monday = pd.date_range(start=date, end=date + pd.offsets.Day(6), freq="W-MON")[
0
]
# 2. Adding a 'ClosestMonday' column with the closest monday for each row in
# a pandas df using apply. Requires you to have a 'Date' column in your df
def get_closest_monday(row):
return pd.date_range(
start=row.Date, end=row.Date + pd.offsets.Day(6), freq="W-MON"
)[0]
df = pd.DataFrame([datetime.date(2011, 7, 2)], columns=["Date"])
df["ClosestMonday"] = df.apply(lambda row: get_closest_monday(row), axis=1)
print(df)
You can start adding one day to date object and stop when it's monday.
>>> d = datetime.date(2011, 7, 2)
>>> while d.weekday() != 0: #0 for monday
... d += datetime.timedelta(days=1)
...
>>> d
datetime.date(2011, 7, 4)
import datetime
d = datetime.date(2011, 7, 2)
while d.weekday() != 0:
d += datetime.timedelta(1)
dateutil has a special feature for this kind of operation and it's the most elegant way I have ever seen yet.
from datetime import datetime
from dateutil.relativedelta import relativedelta, MO
first_monday_date = (datetime(2011,7,2) + relativedelta(weekday=MO(0))).date()
if you want datetime just
first_monday_date = datetime(2011,7,2) + relativedelta(weekday=MO(0))
weekday = 0 ## Monday
dt = datetime.datetime.now().replace(hour=0, minute=0, second=0) ## or any specific date
days_remaining = (weekday - dt.weekday() - 1) % 7 + 1
next_dt = dt + datetime.timedelta(days_remaining)
Generally to find any date from day of week from today:
def getDateFromDayOfWeek(dayOfWeek):
week_days = ["monday", "tuesday", "wednesday",
"thursday", "friday", "saturday", "sunday"]
today = datetime.datetime.today().weekday()
requiredDay = week_days.index(dayOfWeek)
if today>requiredDay:
noOfDays=7-(today-requiredDay)
print("noDays",noOfDays)
else:
noOfDays = requiredDay-today
print("noDays",noOfDays)
requiredDate = datetime.datetime.today()+datetime.timedelta(days=noOfDays)
return requiredDate
print(getDateFromDayOfWeek('sunday').strftime("%d/%m/%y"))
Gives output in format of Day/Month/Year
This will give the first next Monday after given date:
import datetime
def get_next_monday(year, month, day):
date0 = datetime.date(year, month, day)
next_monday = date0 + datetime.timedelta(7 - date0.weekday() or 7)
return next_monday
print get_next_monday(2011, 7, 2)
print get_next_monday(2015, 8, 31)
print get_next_monday(2015, 9, 1)
2011-07-04
2015-09-07
2015-09-07
via list comprehension?
from datetime import *
[datetime.today()+timedelta(days=x) for x in range(0,7) if (datetime.today()+timedelta(days=x)).weekday() % 7 == 0]
(0 at the end is for next monday, returns current date when run on monday)