how to get list of all weeks - python

i tried something like this
year, week_num, day_num = date.today().isocalendar()
weeks = []
week_range_start = 1
week_range_end = 17
for i in range(week_range_start,week_range_end):
curr_week = week_num - i
str_week = str(curr_week) if len(str(curr_week)) == 2 else f'0{curr_week}'
weeks.append(str(year) + str_week)
print(weeks)
my output looks something like this
['202114', '202113', '202112', '202111', '202110', '202109', '202108', '202107', '202106', '202105', '202104', '202103', '202102', '202101', '202100', '2021-1']
this is wrong because there is no 00 week number. week number starts from 1 to 52 and i also getting same 2021 instead of 2020. the output should be
['202114', '202113', '202112', '202111', '202110', '202109', '202108', '202107', '202106', '202105', '202104', '202103', '202102', '202101', '202053', '202052']
and so on if it is a leap year also it should work by changing the range and also need to parameterize the length of the range

Original Question:
I think the problem stems from working with int outputs of .isocalendar() instead of working inside of datetime objects which handle some of these issues.
Here is an example that subtracts off a week at a time using datetime.timedelta(weeks=1):
from datetime import date, timedelta
today = date.today()
weeks = []
for i in range(16):
# Subtract a week from the initial 'today'
today -= timedelta(weeks=1)
# This handles some formatting to make it consistent with expected output:
year, week, _ = today.isocalendar()
weeks.append(str(year) + "{0:02d}".format(week))
print(weeks)
Expected output:
['202114', '202113', '202112', '202111', '202110', '202109', '202108', '202107', '202106', '202105', '202104', '202103', '202102', '202101', '202053', '202052']
Modified Question:
The question changed to focus on how to get a 'list of dates between a start and end number', where start and end are a number of weeks.
To do this: you can first subtract off the number of start weeks; then loop through the remaining weeks between range(start, end), subtracting off one week at a time.
from datetime import date, timedelta
def get_list_of_weeks(start, end):
today = date.today()
today -= timedelta(weeks=start)
weeks = []
for _ in range(start, end):
today -= timedelta(weeks=1)
# This handles some formatting to make it consistent with expected output:
year, week, _ = today.isocalendar()
weeks.append(str(year) + "{0:02d}".format(week))
return weeks
if __name__ == "__main__":
print(list_of_weeks(10, 17))
Expected output:
['202104', '202103', '202102', '202101', '202053', '202052', '202051']

I really went through a lot of documents and found your answer.
Check it took really a lot of time.
from datetime import date, timedelta
def getweeks(limit):
finalres = []
for i in range(limit):
dt = date.today() - timedelta(weeks=i)
year,month,d = dt.year,dt.month,dt.day
week = str(date(year, month, d).isocalendar()[1])
res = str(year) + week
finalres.append(res)
return finalres
num = int(input("Enter how many weeks you want ? : "))
print(getweeks(num))
This answer needs upvote :)

Related

How to return all weekdays in a range of dates, sorted in ascending order

from datetime import datetime
from datetime import timedelta
#this is the start day
day = input()
#this is number of days input
num=int(input())
#this is the start date of the shipment
temp = input()
#this is the date format the string into a day using the strptime object
start_day = datetime.strptime(day, '%A')
#this line will format the string input into a date
format1 = datetime.strptime(temp, '%d-%m-%Y')
#this line will add number input onto the date
arrival = format1 + timedelta(days=num)
for i in range(num):
a = arrival - timedelta(days=i)
if a.weekday() <5 :
print(a.strftime('%d-%m-%Y'))
The above code gives me three weekday dates but I am expecting four.
This is my output:
05-03-2019
04-03-2019
01-03-2019
but I need this:
01-03-2019
04-03-2019
05-03-2019
06-03-2019
All dates starting with the oldest first e.g. ascending order.
Here is the assignment I have:
Radan Logistics is a mid sized Shipping Company known for its Customer oriented delivery services. The Company Management intended to place an information kiosk in their Head Office which would help their Customers to fetch all the desired information with regards to their shipment. One such vital information that Customers would prefer to know is the details of the working days of the Company which would help them track their shipments.
Help the Management write a program for the kiosk, that when given the start day, number of days 'n' and the start date, will output the dates of the 'n' business days (excluding Saturday and Sunday).
Input Format:
The first line of input is a String, the start day.
The second line of the input is the number of days.
Third line is a string that correponds to the start date of the shipment.
Output Format:
Output is list of dates of n working days separated by new line.
Sample Input 1:
Monday
7
03-12-2007
Sample Output 1:
04-12-2007
05-12-2007
06-12-2007
07-12-2007
10-12-2007
11-12-2007
Sample Input 2:
Thursday
10
25-02-2012
Sample Output 2:
26-02-2012
29-02-2012
01-03-2012
02-03-2012
03-03-2012
04-03-2012
07-03-2012
08-03-2012
09-03-2012
The issue seems to be that you're looping through an ascending range of numbers, but that number is subtracted to get the result. For example 10-1=9, 10-2=8, 10-3=7, etc. You can instead loop through range(num) in descending order. Also, range() by default goes from index zero up to and not including num. To have num included, you may want range(num + 1)
for i in reversed(range(num + 1)):
a = arrival - timedelta(days=i)
if a.weekday() <5 :
print(a.strftime('%d-%m-%Y'))
To show 5 days you have to make a.weekday() <=5 not num+1
and add reversed to range to reverse the showing of data
for i in reversed(range(num)):
a = arrival - timedelta(days=i)
if a.weekday() <=5 :
print(a.strftime('%d-%m-%Y'))
import datetime
start = '01-03-2019'
num_days = 7
date_list = [datetime.datetime.strptime(start, "%d-%m-%Y") + datetime.timedelta(days=x) for x in range(num_days)]
list_of_weekdays = [day.strftime('%d-%m-%Y') for day in date_list if day.isoweekday() in range(1, 6)]
[print(day) for day in list_of_weekdays[::-1]]
Print range of dates in descending order, i.e. from newest to oldest.
from datetime import datetime, timedelta
def range_of_dates_from_interval(start, end, date_format='%d-%m-%Y'):
start_date = datetime.strptime(start, date_format).date()
end_date = datetime.strptime(end, date_format).date()
d = timedelta(days=1)
date = end_date
while date != start_date:
print(date.strftime(date_format))
date -= d
print(date.strftime(date_format))
def range_of_dates_with_step(start, amount_days, date_format='%d-%m-%Y'):
start_date = datetime.strptime(start, date_format).date()
d = timedelta(days=1)
for i in range(amount_days-1, -1, -1):
print((start_date + d*i).strftime(date_format))
date_format = '%d-%m-%Y'
# test first function
start = '29-03-2019'
end = '02-04-2019'
range_of_dates_from_interval(start, end, date_format=date_format)
#02-04-2019
#01-04-2019
#31-03-2019
#30-03-2019
#29-03-2019
# test second function
start = '29-03-2019'
amount_days = 5
range_of_dates_with_step(start, amount_days, date_format=date_format)
#02-04-2019
#01-04-2019
#31-03-2019
#30-03-2019
#29-03-2019
EDIT: answer of the assignment
import datetime
# not needed but useful for display information
def weekdays_iso(day_num_format=True) -> dict:
out = {}
d0 = datetime.date.fromordinal(1) # day zero
d, a_day = d0, datetime.timedelta(days=1)
for i in range(7):
if day_num_format:
out[d.strftime("%A")] = i+1
else:
out[i+1] = d.strftime("%A")
d += a_day
return out
# main function
def get_business_days(num_b_days, start, date_format='%d-%m-%Y') -> list:
b_days = []
start_date = datetime.datetime.strptime(start, date_format).date()
b_day, a_day = start_date, datetime.timedelta(days=1)
while num_b_days > 1:
b_day += a_day
if b_day.isoweekday() not in {6, 7}:
b_days.append(b_day)
num_b_days -= 1
return b_days
WEEKDAYS_ISO = weekdays_iso(day_num_format=False)
date_format = '%d-%m-%Y'
Test 1
start = "03-12-2007"
n_b_days = 7
# result
b_days = get_business_days(n_b_days, start, date_format=date_format)
# check
for d in b_days:
print(d.strftime(date_format), WEEKDAYS_ISO[d.isoweekday()])
Output 1:
04-12-2007 Tuesday
05-12-2007 Wednesday
06-12-2007 Thursday
07-12-2007 Friday
10-12-2007 Monday
11-12-2007 Tuesday
Test 2
start = "25-02-2012"
n_b_days = 10
# result
b_days = get_business_days(n_b_days, start, date_format=date_format)
# check
for d in b_days:
print(d.strftime(date_format), WEEKDAYS_ISO[d.isoweekday()])
Output 2:
27-02-2012 Monday
28-02-2012 Tuesday
29-02-2012 Wednesday
01-03-2012 Thursday
02-03-2012 Friday
05-03-2012 Monday
06-03-2012 Tuesday
07-03-2012 Wednesday
08-03-2012 Thursday

How to check whether a date is in the next week, python

Basically, I'm trying to check whether a date, e.g. 2021-07-08, is in the next week, or the week after that, or neither.
#I can call the start and end dates of the current week
start = tday - timedelta(days=tday.weekday())
end = start + timedelta(days=6)
print("Today: " + str(tday))
print("Start: " + str(start))
print("End: " + str(end))
# and I can get the current week number.
curr_week = datetime.date.today().strftime("%V")
print(curr_week)
Is there a better way than getting a list of dates in curr_week + 1 and then checking whether date is in in that list?
Thanks so much
GENERAL ANSWER
It is best to stick to datetime and timedelta, since this handles all edge cases like year changes, years with 53 weeks etc.
So find the number of the next week, and compare the weeknumber of the week you want to check against that.
import datetime
# Date to check in date format:
check_date = datetime.datetime.strptime("2021-09-08", "%Y-%d-%m").date()
# Current week number:
curr_week = datetime.date.today().strftime("%V")
# number of next week
next_week = (datetime.date.today()+datetime.timedelta(weeks=1)).strftime("%V")
# number of the week after that
week_after_next_week = (datetime.date.today()+datetime.timedelta(weeks=2)).strftime("%V")
# Compare week numbers of next weeks to the week number of the date to check:
if next_week == check_date.strftime("%V"):
# Date is within next week, put code here
pass
elif week_after_next_week == check_date.strftime("%V"):
# Date is the week after next week, put code here
pass
OLD ANSWER
This messes up around year changes, and modulo doesn't fix it because there are years with 53 weeks.
You can compare the week numbers by converting them to integers. You don't need to create a list of all dates within the next week.
import datetime
# Date to check in date format:
check_date = datetime.datetime.strptime("2021-07-08", "%Y-%d-%m").date()
# Current week number, make it modulo so that the last week is week 0:
curr_week = int(datetime.date.today().strftime("%V"))
# Compare week numbers:
if curr_week == (int(check_date.strftime("%V"))-1):
# Date is within next week, put code here
pass
elif curr_week == (int(check_date.strftime("%V"))-2):
# Date is the week after next week, put code here
pass
You can cast the date you want to check in datetime, and then compare the week numbers.
# date you want to check
date = datetime.datetime.strptime("2021-07-08","%Y-%m-%d")
# current date
tday = datetime.date.today()
# compare the weeks
print(date.strftime("%V"))
print(tday.strftime("%V"))
27
32
[see Alfred's answer]
You can get the week number directly as an integer integer from the IsoCalendarDate representation of each date.
from datetime import datetime
date_format = '%Y-%m-%d'
t_now = datetime.strptime('2021-08-11', date_format)
target_date = datetime.strptime('2021-08-18', date_format)
Just using datetime comparing:
from datetime import datetime, timedelta
def in_next_week(date):
""" -1: before; 0: in; 1: after next week;"""
today = datetime.today()
this_monday = today.date() - timedelta(today.weekday())
start = this_monday + timedelta(weeks=1)
end = this_monday + timedelta(weeks=2)
return -1 if date < start else 0 if date < end else 1
Test cases:
for i in range(14):
dt = datetime.today().date() + timedelta(days=i)
print(dt, in_next_week(dt))

create a list of dates with a while loop python

I want tot create a list of dates starting from 10/09/2020 with increments of 182 days until reaching 05/03/2020.
my code is this :
start_date="10/09/2020"
last_date="05/03/2020"
start_date=datetimedatetime.strptime(date,"%d/%m/%Y").date()
last_date=datetimedatetime.strptime(date,"%d/%m/%Y").date()
dates=[]
while dates[-1] != last_date:
i=star_date+timedelta(days=182)
dates.append(i)
dates[i]=i+timedelta(days=pago_cupon)
I don't know what's your problem.
You can try this code
from datetime import date, timedelta
start_day = date(year=2020, month=9, day=10)
end_day = date(year=2021, month=3, day=5)
one_data_delta = timedelta(days=1)
res = []
while end_day != start_day:
start_day += one_data_delta
res.append(start_day)
print(res)
A few problems:
You had a spelling mistake in your for loop star_date instead of start_date.
Also, you may want to change the comparison from != to less than equals or more than equals.
I am checking against (last_date - timedelta(days=182)) so that we won't exceed the last_date.
Your original start date is after your original end date.
As an example, I have adjusted the end day to be a couple years in the future.
I'm appending the dates as text.
from datetime import datetime, timedelta
start="10/09/2020"
last="05/03/2022"
start_date=datetime.strptime(start,"%d/%m/%Y")
last_date=datetime.strptime(last,"%d/%m/%Y")
dates=[]
while start_date <= (last_date - timedelta(days=182)):
start_date += timedelta(days=182)
dates.append(start_date.strftime("%d/%m/%Y"))
# not quite sure what you are trying to do here:
#dates[i]=i+timedelta(days=pago_cupon)
print(dates)
Output:
['11/03/2021', '09/09/2021']

python get day if its in a dates range

I'm trying to check if first date of the month and the last date of the month lies in a range of dates (the range is 7 days window starting from current date) . below is an example for what I'm trying to achieve:
import datetime, calendar
today = datetime.date.today()
date_list = [today + datetime.timedelta(days=x) for x in range(0, 7)]
lastDayOfMonth = today.replace(day=calendar.monthrange(today.year,today.month)[-1])
if 1 in [ date_list[i].day for i in range(0, len(date_list))]:
print "we have first day of month in range"
elif lastDayOfMonth in [ date_list[i].day for i in range(0, len(date_list))]:
print " we have last date of month in the range"
I'm wondering if there is a cleaner way for doing that? I also want to print the exact date if I find it in the list but I don't know how without expanding the for loop in the if statement and save print date_list[i] if it matches my condition. so instead of printing the message when I find the first day in the range I should print the actual date. same for last date.
Thanks in advance!
The only thing I can come up with, without having to make use of iteration is:
import datetime, calendar
today = datetime.date.today()
week_from_today = today + datetime.timedelta(days=6)
last_day_of_month = today.replace(day=calendar.monthrange(today.year,today.month)[-1])
if today.month != week_from_today.month:
print datetime.date(week_from_today.year, week_from_today.month, 1)
elif today <= last_day_of_month <= week_from_today:
print last_day_of_month
since today it's 2016-06-02 it's hard to test the code.
Try changing the variable today to another day. I used the dates 2016-05-25 and 2016-05-26 to test the code.
to set a custom date: today = datetime.date(yyyy, m, d)

Getting a year and month from a number of a months in Python

I'd like to write a function which:
takes in parameter: a number of months (int)
returns the year (int) and the month (int) of the timedelta between now and the number of input months.
Example : we are in may 2014, so:
myfunc(0) should return (2014, 5)
myfunc(12) should return (2013, 5)
myfunc(5) should return (2013, 12)
etc.
There is lots of documentation about datetime and calendar, so much that I'm a bit lost. Thanks for help.
Note: I need to get an accurate way to do it, not an approximation :)
import datetime
def myfunc(num_of_months):
today = datetime.date.today()
num_of_months = today.year * 12 + today.month - 1 - num_of_months
year = num_of_months / 12
month = num_of_months % 12 + 1
return year, month
from time import strftime, localtime, time
from calendar import monthrange
def uberdate(n):
if n == 0: return strftime('%Y, %m').split(', ')
month = int(strftime('%m'))
aDay = 60*60*24
offset = aDay # One day to start off with
for i in range(0, n):
while int(strftime('%m', localtime(time()-offset))) == month:
offset = offset+aDay
month = int(strftime('%m', localtime(time()-offset)))
return strftime('%Y, %m', localtime(time()-offset)).split(', ')
print(uberdate(5))
This produces:
[torxed#archie ~]$ python test.py
[2013, 12]
Don't know why i got the downvote, but to quote OP:
Example : we are in may 2014, so:
myfunc(5) should return (2013, 12) etc.
And this is what my function produces...
Feedback people, give it before downvoting randomly.
You can use python-dateutil module for this. https://pypi.python.org/pypi/python-dateutil
def return_year_date(delta_month):
from datetime import date
from dateutil.relativedelta import relativedelta
new_date = date.today() + relativedelta(months= -delta_month)
return new_date.year, new_date.month
EDITED (Changed the month addition to make the accuracy perfect)
Now you can put negative number of months and get past dates
I think this is what youre looking for
import datetime
from dateutil.relativedelta import *
def calculate_date(number_months):
time_now = datetime.datetime.now() # Get now time
time_future = time_now + relativedelta(months=+number_months) # Add months
return time_future.year,time_future.month #Return year,month
I've tested this script in my coputer and works perfectly
>>> calculate_data(5)
(2014, 10)

Categories

Resources