Week ending date with Sunday being the first day of the week - python

I am trying to get the week ending date for a list of dates. I found the below code and it works for a traditional Monday thru Sunday week but I need a Sunday thru Saturday week (Sunday being the first day of the week).
from datetime import datetime, timedelta
date_str = '2019-06-16'
date_obj = datetime.strptime(date_str, '%Y-%m-%d')
start_of_week = date_obj - timedelta(days=date_obj.weekday())
end_of_week = start_of_week + timedelta(days=6)
print(start_of_week)
print(end_of_week)
The above code returns:
2019-06-10 00:00:00
2019-06-16 00:00:00
and I need it to return this:
2019-06-16 00:00:00
2019-06-22 00:00:00

So weekday returns 0 for Monday and 6 for Sunday. To change that to 0 for Sunday and 6 for Saturday do
start_of_week = date_obj - timedelta((date_obj.weekday() + 1) % 7)

I think in python, Sunday is the start day of a week, LOL. Code below may help you.
from datetime import datetime, timedelta
# this may be the func you need.
def date_start_end(date):
"""
calc the start and end date for input date. Sunday is the start day for a week.
:param date: any date
:return: st: the start date(Sunday) for this week
:return: end: the end date(Saturday) for this week
"""
weekDate = int(date.strftime('%w'))
st = date + timedelta(-weekDate)
end = date + timedelta(6 - weekDate)
return st, end
date = datetime(2019, 6, 16)
st, end = date_start_end(date)
print(st)
print(end)
>>>2019-06-16 00:00:00
>>>2019-06-22 00:00:00

Adding in my two cents. Datetime also has an isoweekday method that has Monday at 1 and Sunday at 7. Similar to #Deepstop's answer but a bit shorter:
start_of_week = date_sample - timedelta(days=date_sample.isoweekday()%7)

Related

How can I find the fiscal Week of date in Pandas

I have a column with many dates: sample of the said list below
Dates
1 2019-02-01
2 2018-03-10
3 2019-08-01
4 2020-02-07
I would like to have it so that if input a date, of any year I can get the week number.
However, the fiscal year starts on Aug 1 of any given year.
I tried just shifting the date to Jan 1 but it's different for every year due to leap years.
data['Dates'] = pd.to_datetime(data['Dates'])
data['Week'] = (data['Dates'] - timedelta(days=215)).week
print(data)
how can I get a result similar to this one below
Dates Week
1 2019-02-01 27
2 2018-03-10 32
3 2019-08-01 1
4 2020-02-07 28
-Note: the weeks are probably incorrect.
The other answer ignores the fiscal year part of the OP. I am leaving the fiscal year start date calc to the reader but this will calculate the week number (where Monday is the start of the week) from an arbitrary start date.
from dateutil import relativedelta
from datetime import date, datetime, timedelta
NEXT_MONDAY = relativedelta.relativedelta(weekday=relativedelta.MO)
LAST_MONDAY = relativedelta.relativedelta(weekday=relativedelta.MO(-1))
ONE_WEEK = timedelta(weeks=1)
def week_in_fiscal_year(d: date, fiscal_year_start: date) -> int:
fy_week_2_monday = fiscal_year_start + NEXT_MONDAY
if d < fy_week_2_monday:
return 1
else:
cur_week_monday = d + LAST_MONDAY
return int((cur_week_monday - fy_week_2_monday) / ONE_WEEK) + 2
adapted from this post
Convert it to a datetime, then call datetime.date(2010, 6, 16).strftime("%V")4
You can also use isocalendar which will return a tuple, as opposed to a string above datetime.date(2010, 6, 16).isocalendar()[1]
How to get week number in Python?

How to check it's between Sunday 5:30PM and Friday 5:30PM?

How do I check if the current time is between Sunday 5:30 PM and Friday 5:30 PM?
I can find the day and time ranges separately but I think the time has to be combined with the day.
import datetime
import time
now = datetime.datetime.now()
if 0 <= now.weekday() <= 4:
print ("It's a weekday!")
if time(17, 30) <= now.time() <= time(17, 30):
print "and it's in range"
You can check the following 3 conditions:
The day is not Saturday
Either the day is not Friday, or the time is before 17:30
Either the day is not Sunday, or the time is after 17:30
In code, this is equivalent to:
from datetime import datetime, time
now = datetime.now()
if (now.weekday != 5
and (now.weekday != 4 or now.time() <= time(17, 30))
and (now.weekday != 6 or now.time() >= time(17, 30))):
print("In range!")
You can simply get the datetime of the most recent Sunday at 5:30pm, and then check if it's within exactly 5 days:
import datetime
now = datetime.datetime.now()
last_sunday = next((now - i * datetime.timedelta(days=1)) for i in range(7) if (now - i * datetime.timedelta(days=1)).weekday() == 6)
last_sunday_at_530 = datetime.datetime(year=last_sunday.year, month=last_sunday.month, day=last_sunday.day, hour=17, minute=30)
if (now - last_sunday_at_530) < datetime.timedelta(days=5):
print("now is between Sunday at 5:30pm and Friday at 5:30pm")
else:
print("Now is after 5:30pm on Friday but before Sunday at 5:30pm
If you want to check the reverse (after Friday but before Sunday) then you can simply start at last_friday and count forwards by only two days.
Which time of day is within the range depends on the day:
On Sunday, times after 5:30 PM are in.
From Monday to Thursday, the time does not matter.
On Friday, times before 5:30 are in.
This leads to the following code:
import datetime
now = datetime.datetime.now()
d = now.weekday()
t = now.time()
if (
d == 6 and t >= datetime.time(17, 30) # Sunday
or 0 <= d <= 3 # Monday–Thursday
or d == 4 and t <= datetime.time(17, 30) # Friday
):
print("In range")

How do i count with datetime and list it?

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;
}

Finding dates between two dates

Say I want to find all Mondays between two dates, date_A and date_B
from datetime import date, timedelta
days_to_substract = 50
date_A = date.today()-timedelta(days=days_to_subtract)
date_B = date.today()
How can I do this? Is there any way to iterate between dates?
you can iterate over date range with generator:
def date_range(date1,date2):
while date1 < date2:
yield date1
date1 = date1 + timedelta(days=1)
and iterate it like this:
for dat in date_range(date_A,date_B):
<your code here>
Find last Monday from current date and find remaining based on 7 days difference:
from datetime import date, timedelta
days_to_substract = 50
date_A = date.today()-timedelta(days=days_to_substract)
date_B = date.today()
cDay = date_B - timedelta(days=date_B.weekday())
print cDay
while cDay > date_A:
cDay = cDay - timedelta(days=7)
print cDay
Output:
2014-03-24
2014-03-17
2014-03-10
2014-03-03
2014-02-24
2014-02-17
2014-02-10
2014-02-03
Maybe this :
from datetime import date, timedelta
days_to_substract = 50
date_A = date.today()-timedelta(days=days_to_substract)
date_B = date.today()
date_tmp = date_A
numOfMondays = 0
deltaStep = 1
while date_tmp < date_B:
if date_tmp.strftime("%A") != "Monday":
print("Date before first monday {}".format(date_tmp))
date_tmp += timedelta(days=1)
else:
print("Monday : {}".format(date_tmp))
date_tmp += timedelta(days=7)
numOfMondays += 1
print("from {} to {} there are {} monday".format(date_A, date_B, numOfMondays))
with output
Date before first monday 2014-02-05
Date before first monday 2014-02-06
Date before first monday 2014-02-07
Date before first monday 2014-02-08
Date before first monday 2014-02-09
Monday : 2014-02-10
Monday : 2014-02-17
Monday : 2014-02-24
Monday : 2014-03-03
Monday : 2014-03-10
Monday : 2014-03-17
Monday : 2014-03-24
from 2014-02-04 to 2014-03-26 there are 7 monday
Do you mean something like this?
def day_iter(start, end):
step = timedelta(days=1)
for i in range((end - start).days):
yield start + i*step
end = date.today()
start = end - timedelta(days=50)
for day in day_iter(start, end):
day.weekday() == 0:
print day.strftime("%A %Y-%m-%d")
Output:
Monday 2014-02-10
Monday 2014-02-17
Monday 2014-02-24
Monday 2014-03-03
Monday 2014-03-10
Monday 2014-03-17
Monday 2014-03-24
You could also do something like this:
today = date.today()
past = today - timedelta(50)
if past.weekday() != 0:
monday = past + timedelta(7 - past.weekday())
else:
monday = past
one_week = timedelta(7)
while monday < today:
print monday
monday += one_week
which outputs:
2014-02-10
2014-02-17
2014-02-24
2014-03-03
2014-03-10
2014-03-17
2014-03-24
And you can generalize this into a function like this:
def past_weekdays(depth, weekday):
today = date.today()
past = today - timedelta(depth)
if past.weekday() != weekday:
past_day = past + timedelta((7 + (weekday - past.weekday())) % 7)
else:
past_day = past
one_week = timedelta(7)
while past_day < today:
yield past_day
past_day += one_week

Find the date for the first Monday after a given date

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)

Categories