Get week of UK fiscal year - python

I want to get the week number corresponding to the UK fiscal year (which runs 6th April to 5th April). report_date.strftime('%V') will give me the week number corresponding to the calendar year (1st January to 31st December).
For example, today is 2nd February which is UK fiscal week 44, but %V would return 05.
I've seen the https://pypi.org/project/fiscalyear/ library but it doesn't seem to offer a way to do this. I know that I can work out the number of days since April 6th and divide by 7, but just curious if there's a better way.

This does the job in Python. It counts the number of days since April 6th of the given year (formatted_report_date), and if the answer is negative (because April 6th hasn't passed yet), then a year is subtracted. Then divide by 7 and add 1 (for 1-indexing). The answer will be between 1-53.
def get_fiscal_week(formatted_report_date):
"""
Given a date, returns the week number (from 1-53) since the last April 6th.
:param formatted_report_date: the formatted date to be converted into a
fiscal week.
"""
from datetime import datetime
fiscal_start = formatted_report_date.replace(month=4, day=6)
days_since_fiscal_start = (formatted_report_date - fiscal_start).days
if days_since_fiscal_start < 0:
fiscal_start = fiscal_start.replace(year=fiscal_start.year-1)
days_since_fiscal_start = (formatted_report_date - fiscal_start).days
return (days_since_fiscal_start / 7) + 1

Related

Return Earliest Date based on value within dataset

I am working with REIGN data that documents elections and leaders in countries around the world (https://www.oneearthfuture.org/datasets/reign)
In the dataset there is an boolean election anticipation variable that turns from 0 to 1 to denote that an election is anticipated in at least the next 6 months, possibly sooner.
Excel sheet of data in question
I want to create a new column that returns the earliest date of when anticipation (column N) turns 1 (i.e. when was the election first anticipated).
So for example, with Afghanistan in column we have an election in 2014 and in 2017.
In column N we see it turn from 0 to 1 on Oct, 2014 (election anticipated) and then we see it go back to 0 on July, 2014 (election concluded) until it goes back to 1 on Jan, 2019 (election anticipated) and then turns back to 0 on Oct, 2019.
So if successful, I would capture Oct, 2014 (election anticipated) and Jan, 2019 (election anticipated) as election announcement dates in a new column along with any other dates an election was anticipated.
Currently I have the following:
#bringing in Reign CSV
regin = pd.read_csv('REIGN_2021_7(1).csv')
#shows us the first 5 rows to make sure they look good
print(regin.head())
#show us the rows and columns in the file
regin.shape
#Getting our index
print(regin.columns)
#adding in a date column that concatenates year and month
regin['date'] = pd.to_datetime(regin[['year', 'month']].assign(DAY=1))
regin.head
#def conditions(s):
if (s['anticipation'] == 1):
return (s['date'])
else:
return 0
regin['announced_date'] = regin.apply(conditions, axis=1)
print(regin.head)
Biggest issue for me is that while this returns the date of when a 1 appears, it does not display the earliest date. How I can loop through the anticipation column and return the minimum date, but do so multiple times as a country will have many elections over the years and there are therefore multiple instances in column N for one country of the anticipation turning on(1) and off(0).
Thanks in advance for any assistance! Let me know if anything is unclear.
If you can loop over your dates, you will probably want to use the datetime module (assuming all dates have the same format):
from datetime import datetime
[...]
earliest_date = datetime.today()
[... loop over data, by country ...]
date1 = datetime.strptime(input_date_string1, date_string_format)
if date1 < earliest_date:
earliest_date = date1
[...]
This module supports (among other things):
parsing date objects from a string (.strptime(in_str, format))
comparison of date objects (date1 > date2)
datetime object from current date + time (.today())
datetime object from arbitrary date (.date(year, month, day))
docs: https://docs.python.org/3/library/datetime.html

Calendar algorithms

I am doing task for my classes. I've got one where I need to show how many day of week (Mondays, Tuesday, Wednesday, Thursday etc.) are in specific month. For an example: March 2017 had 4 mon, 4 tue, 5 wed, 5 th, 5 fri, 4 sat, 4 sun.
So far I did...
class Calendar():
def __init__(self, month, year):
self.month = month
self.year = year
if month < 1 or month > 12:
print("Error 404 month not found")
def show(self):
print(Calendar) ##Just test
test1 = Calendar(0, 2017)
test1.show()
and I'm stuck, because I don't really know how can I find particular day in month using month and year.
I don't think you should use libraries - clearly the task is to come up with algorithm and not to use existing tools. I'm not going to write a code as this is your assignment. But I'll try to help with the approach:
Try defining a single known date that you know is Monday.
Define a single year that you know is a leap year
Define a months list that stores the numbers of days in each month
For any input month and year calculate a number of days from your know date to the first day of the month.
Use modulo 7 operation on the result of step 4 to find the day of the week for the first day in month
Now subtract the number of days in given month (but also check here for leap years) from the first ocurrence of given day of the week and use some more modulo 7 arithmetics to find out the number of particular days of the week in a given month.

Calculate first day of the week, given year and week number of the year

In python, How can we calculate the first day of the week when given a year and the particular week number of the year?
Note that date should be in format YYYY-MM-DD. Year and the week number is given in int format..
I am making the following assumptions about what your question means. If they are off, it should not be hard to adjust the code.
1) The first day of the week is Sunday. (so the answer is always a Sunday)
2) The week in which January 1 falls is week 1 (not 0).
Then the work breaks down into two parts.
a) Figure out the first day of the first week.
b) Add the right number of days onto that.
In Python, it looks as follows:
import datetime
def firstDayOfWeek1(y):
#takes a year and says the date of the first Sunday in the week in which January 1 falls
janDay = datetime.date(y,1,1)
while (janDay.weekday()!=6):#back up until Sunday, change if you hold Sunday is not the first day of the week
janDay=janDay-datetime.timedelta(days=1)
return janDay
def firstDayOfWeekN(y, n):#takes a year and a week number and gives the date of the first Sunday that week
return firstDayOfWeek1(y)+datetime.timedelta(weeks=(n-1))
def formattedFirstDayOfWeekN(y, n):#takes a year and a week number and gives the date of the first Sunday that week
return firstDayOfWeekN(y, n).isoformat()
#example
print formattedFirstDayOfWeekN(2018,2)#2018-01-07, first day of second week of January this year
I am using an algorithm which starts with a close-by date and then simply loops down till it finds the desired result. I am sacrificing some CPU cycles for ease of readability since the cost is not significant. I have done some limited testing but I hope the general idea is clear. Let me know your thoughts.
#This is the input in integer format
input_year = 2018
input_week = 29
#The general idea is that we will go down day by day from a reference date
#till we get the desired result.
#The loop is not computationally intensive since it will
#loop at max around 365 times.
#The program uses Python's ISO standard functions which considers Monday as
#the start of week.
ref_date = date(input_year+1,1,7) #approximation for starting point
#Reasoning behind arguments: Move to next year, January. Using 7 as day
#ensures that the calendar year has moved to the next year
#because as per ISO standard the first week starts in the week with Thursday
isoyear,isoweek,isoday = ref_date.isocalendar()
output_date = ref_date #initialize for loop
while True:
outisoyear,outisoweek,outisoday = output_date.isocalendar()
if outisoyear == input_year and outisoweek == input_week and outisoday == 1:
break
output_date = output_date + timedelta(days=-1)
print(output_date)

Python week number generating

I am trying to generate the number of the week based on the date that user input. I am aware of this following function that will give me the specific week number for the date that i input.
datetime.date(2012,5,21).isocalendar()[1]
my problem is that i want to make the week 1 of my year to start in April 1st instead of Jan 1st. Which means, my calendar for every year starts from April 1 and ends at march 31. Not Jan 1 to dec 31. Is there any build in function i can use?
Use datetime
from datetime import date
end = date(2012, 5, 21)
start = date(2012, 4, 1)
Diff = end - start
print Diff.days / 7 # convert to number of weeks

How to get week number in Python?

How to find out what week number is current year on June 16th (wk24) with Python?
datetime.date has a isocalendar() method, which returns a tuple containing the calendar week:
>>> import datetime
>>> datetime.date(2010, 6, 16).isocalendar()[1]
24
datetime.date.isocalendar() is an instance-method returning a tuple containing year, weeknumber and weekday in respective order for the given date instance.
In Python 3.9+ isocalendar() returns a namedtuple with the fields year, week and weekday which means you can access the week explicitly using a named attribute:
>>> import datetime
>>> datetime.date(2010, 6, 16).isocalendar().week
24
You can get the week number directly from datetime as string.
>>> import datetime
>>> datetime.date(2010, 6, 16).strftime("%V")
'24'
Also you can get different "types" of the week number of the year changing the strftime parameter for:
%U - Week number of the year (Sunday as the first day of the week) as a zero padded decimal number. All days in a new year preceding the first Sunday are considered to be in week 0. Examples: 00, 01, …, 53
%W - Week number of the year (Monday as the first day of the week) as a decimal number. All days in a new year preceding the first Monday are considered to be in week 0. Examples: 00, 01, …, 53
[...]
(Added in Python 3.6, backported to some distribution's Python 2.7's) Several additional directives not required by the C89 standard are included for convenience. These parameters all correspond to ISO 8601 date values. These may not be available on all platforms when used with the strftime() method.
[...]
%V - ISO 8601 week as a decimal number with Monday as the first day of the week. Week 01 is the week containing Jan 4. Examples: 01, 02, …, 53
from: datetime — Basic date and time types — Python 3.7.3 documentation
I've found out about it from here. It worked for me in Python 2.7.6
I believe date.isocalendar() is going to be the answer. This article explains the math behind ISO 8601 Calendar. Check out the date.isocalendar() portion of the datetime page of the Python documentation.
>>> dt = datetime.date(2010, 6, 16)
>>> wk = dt.isocalendar()[1]
24
.isocalendar() return a 3-tuple with (year, wk num, wk day). dt.isocalendar()[0] returns the year,dt.isocalendar()[1] returns the week number, dt.isocalendar()[2] returns the week day. Simple as can be.
There are many systems for week numbering. The following are the most common systems simply put with code examples:
ISO: First week starts with Monday and must contain the January 4th (or first Thursday of the year). The ISO calendar is already implemented in Python:
>>> from datetime import date
>>> date(2014, 12, 29).isocalendar()[:2]
(2015, 1)
North American: First week starts with Sunday and must contain the January 1st. The following code is my modified version of Python's ISO calendar implementation for the North American system:
from datetime import date
def week_from_date(date_object):
date_ordinal = date_object.toordinal()
year = date_object.year
week = ((date_ordinal - _week1_start_ordinal(year)) // 7) + 1
if week >= 52:
if date_ordinal >= _week1_start_ordinal(year + 1):
year += 1
week = 1
return year, week
def _week1_start_ordinal(year):
jan1 = date(year, 1, 1)
jan1_ordinal = jan1.toordinal()
jan1_weekday = jan1.weekday()
week1_start_ordinal = jan1_ordinal - ((jan1_weekday + 1) % 7)
return week1_start_ordinal
>>> from datetime import date
>>> week_from_date(date(2014, 12, 29))
(2015, 1)
MMWR (CDC): First week starts with Sunday and must contain the January 4th (or first Wednesday of the year). I created the epiweeks package specifically for this numbering system (also has support for the ISO system). Here is an example:
>>> from datetime import date
>>> from epiweeks import Week
>>> Week.fromdate(date(2014, 12, 29))
(2014, 53)
Here's another option:
import time
from time import gmtime, strftime
d = time.strptime("16 Jun 2010", "%d %b %Y")
print(strftime(d, '%U'))
which prints 24.
See: http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior
The ISO week suggested by others is a good one, but it might not fit your needs. It assumes each week begins with a Monday, which leads to some interesting anomalies at the beginning and end of the year.
If you'd rather use a definition that says week 1 is always January 1 through January 7, regardless of the day of the week, use a derivation like this:
>>> testdate=datetime.datetime(2010,6,16)
>>> print(((testdate - datetime.datetime(testdate.year,1,1)).days // 7) + 1)
24
Generally to get the current week number (starts from Sunday):
from datetime import *
today = datetime.today()
print today.strftime("%U")
For the integer value of the instantaneous week of the year try:
import datetime
datetime.datetime.utcnow().isocalendar()[1]
If you are only using the isocalendar week number across the board the following should be sufficient:
import datetime
week = date(year=2014, month=1, day=1).isocalendar()[1]
This retrieves the second member of the tuple returned by isocalendar for our week number.
However, if you are going to be using date functions that deal in the Gregorian calendar, isocalendar alone will not work! Take the following example:
import datetime
date = datetime.datetime.strptime("2014-1-1", "%Y-%W-%w")
week = date.isocalendar()[1]
The string here says to return the Monday of the first week in 2014 as our date. When we use isocalendar to retrieve the week number here, we would expect to get the same week number back, but we don't. Instead we get a week number of 2. Why?
Week 1 in the Gregorian calendar is the first week containing a Monday. Week 1 in the isocalendar is the first week containing a Thursday. The partial week at the beginning of 2014 contains a Thursday, so this is week 1 by the isocalendar, and making date week 2.
If we want to get the Gregorian week, we will need to convert from the isocalendar to the Gregorian. Here is a simple function that does the trick.
import datetime
def gregorian_week(date):
# The isocalendar week for this date
iso_week = date.isocalendar()[1]
# The baseline Gregorian date for the beginning of our date's year
base_greg = datetime.datetime.strptime('%d-1-1' % date.year, "%Y-%W-%w")
# If the isocalendar week for this date is not 1, we need to
# decrement the iso_week by 1 to get the Gregorian week number
return iso_week if base_greg.isocalendar()[1] == 1 else iso_week - 1
I found these to be the quickest way to get the week number; all of the variants.
from datetime import datetime
dt = datetime(2021, 1, 3) # Date is January 3rd 2021 (Sunday), year starts with Friday
dt.strftime("%W") # '00'; Monday is considered first day of week, Sunday is the last day of the week which started in the previous year
dt.strftime("%U") # '01'; Sunday is considered first day of week
dt.strftime("%V") # '53'; ISO week number; result is '53' since there is no Thursday in this year's part of the week
Further clarification for %V can be found in the Python doc:
The ISO year consists of 52 or 53 full weeks, and where a week starts on a Monday and ends on a Sunday. The first week of an ISO year is the first (Gregorian) calendar week of a year containing a Thursday. This is called week number 1, and the ISO year of that Thursday is the same as its Gregorian year.
https://docs.python.org/3/library/datetime.html#datetime.date.isocalendar
NOTE: Bear in mind the return value is a string, so pass the result to a int constructor if you need a number.
I summarize the discussion to two steps:
Convert the raw format to a datetime object.
Use the function of a datetime object or a date object to calculate the week number.
Warm up
from datetime import datetime, date, time
d = date(2005, 7, 14)
t = time(12, 30)
dt = datetime.combine(d, t)
print(dt)
1st step
To manually generate a datetime object, we can use datetime.datetime(2017,5,3) or datetime.datetime.now().
But in reality, we usually need to parse an existing string. we can use strptime function, such as datetime.strptime('2017-5-3','%Y-%m-%d') in which you have to specific the format. Detail of different format code can be found in the official documentation.
Alternatively, a more convenient way is to use dateparse module. Examples are dateparser.parse('16 Jun 2010'), dateparser.parse('12/2/12') or dateparser.parse('2017-5-3')
The above two approaches will return a datetime object.
2nd step
Use the obtained datetime object to call strptime(format). For example,
python
dt = datetime.strptime('2017-01-1','%Y-%m-%d') # return a datetime object. This day is Sunday
print(dt.strftime("%W")) # '00' Monday as the 1st day of the week. All days in a new year preceding the 1st Monday are considered to be in week 0.
print(dt.strftime("%U")) # '01' Sunday as the 1st day of the week. All days in a new year preceding the 1st Sunday are considered to be in week 0.
print(dt.strftime("%V")) # '52' Monday as the 1st day of the week. Week 01 is the week containing Jan 4.
It's very tricky to decide which format to use. A better way is to get a date object to call isocalendar(). For example,
python
dt = datetime.strptime('2017-01-1','%Y-%m-%d') # return a datetime object
d = dt.date() # convert to a date object. equivalent to d = date(2017,1,1), but date.strptime() don't have the parse function
year, week, weekday = d.isocalendar()
print(year, week, weekday) # (2016,52,7) in the ISO standard
In reality, you will be more likely to use date.isocalendar() to prepare a weekly report, especially in the Christmas-New Year shopping season.
You can try %W directive as below:
d = datetime.datetime.strptime('2016-06-16','%Y-%m-%d')
print(datetime.datetime.strftime(d,'%W'))
'%W': Week number of the year (Monday as the first day of the week) as a decimal number. All days in a new year preceding the first Monday are considered to be in week 0. (00, 01, ..., 53)
For pandas users, if you want to get a column of week number:
df['weekofyear'] = df['Date'].dt.week
isocalendar() returns incorrect year and weeknumber values for some dates:
Python 2.7.3 (default, Feb 27 2014, 19:58:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime as dt
>>> myDateTime = dt.datetime.strptime("20141229T000000.000Z",'%Y%m%dT%H%M%S.%fZ')
>>> yr,weekNumber,weekDay = myDateTime.isocalendar()
>>> print "Year is " + str(yr) + ", weekNumber is " + str(weekNumber)
Year is 2015, weekNumber is 1
Compare with Mark Ransom's approach:
>>> yr = myDateTime.year
>>> weekNumber = ((myDateTime - dt.datetime(yr,1,1)).days/7) + 1
>>> print "Year is " + str(yr) + ", weekNumber is " + str(weekNumber)
Year is 2014, weekNumber is 52
Let's say you need to have a week combined with the year of the current day as a string.
import datetime
year,week = datetime.date.today().isocalendar()[:2]
week_of_the_year = f"{year}-{week}"
print(week_of_the_year)
You might get something like 2021-28
If you want to change the first day of the week you can make use of the calendar module.
import calendar
import datetime
calendar.setfirstweekday(calendar.WEDNESDAY)
isodate = datetime.datetime.strptime(sweek,"%Y-%m-%d").isocalendar()
week_of_year = isodate[1]
For example, calculate the sprint number for a week starting on WEDNESDAY:
def calculate_sprint(sweek):
calendar.setfirstweekday(calendar.WEDNESDAY)
isodate=datetime.datetime.strptime(sweek,"%Y-%m-%d").isocalendar()
return "{year}-{month}".format(year=isodate[0], month=isodate[1])
calculate_sprint('2021-01-01')
>>>'2020-53'
We have a similar issue and we came up with this logic
I have tested for 1year test cases & all passed
import datetime
def week_of_month(dt):
first_day = dt.replace(day=1)
dom = dt.day
if first_day.weekday() == 6:
adjusted_dom = dom
else:
adjusted_dom = dom + first_day.weekday()
if adjusted_dom % 7 == 0 and first_day.weekday() != 6:
value = adjusted_dom / 7.0 + 1
elif first_day.weekday() == 6 and adjusted_dom % 7 == 0 and adjusted_dom == 7:
value = 1
else:
value = int(ceil(adjusted_dom / 7.0))
return int(value)
year = 2020
month = 01
date = 01
date_value = datetime.datetime(year, month, date).date()
no = week_of_month(date_value)
userInput = input ("Please enter project deadline date (dd/mm/yyyy/): ")
import datetime
currentDate = datetime.datetime.today()
testVar = datetime.datetime.strptime(userInput ,"%d/%b/%Y").date()
remainDays = testVar - currentDate.date()
remainWeeks = (remainDays.days / 7.0) + 1
print ("Please pay attention for deadline of project X in days and weeks are : " ,(remainDays) , "and" ,(remainWeeks) , "Weeks ,\nSo hurryup.............!!!")
A lot of answers have been given, but id like to add to them.
If you need the week to display as a year/week style (ex. 1953 - week 53 of 2019, 2001 - week 1 of 2020 etc.), you can do this:
import datetime
year = datetime.datetime.now()
week_num = datetime.date(year.year, year.month, year.day).strftime("%V")
long_week_num = str(year.year)[0:2] + str(week_num)
It will take the current year and week, and long_week_num in the day of writing this will be:
>>> 2006

Categories

Resources