Converting week numbers to dates - python

Say I have a week number of a given year (e.g. week number 6 of 2014).
How can I convert this to the date of the Monday that starts that week?
One brute force solution I thought of would be to go through all Mondays of the year:
date1 = datetime.date(1,1,2014)
date2 = datetime.date(12,31,2014)
def monday_range(date1,date2):
while date1 < date2:
if date1.weekday() == 0:
yield date1
date1 = date1 + timedelta(days=1)
and store a hash from the first to the last Monday of the year, but this wouldn't do it, since, the first week of the year may not contain a Monday.

You could just feed the data into time.asctime().
>>> import time
>>> week = 6
>>> year = 2014
>>> atime = time.asctime(time.strptime('{} {} 1'.format(year, week), '%Y %W %w'))
>>> atime
'Mon Feb 10 00:00:00 2014'
EDIT:
To convert this to a datetime.date object:
>>> datetime.datetime.fromtimestamp(time.mktime(atime)).date()
datetime.date(2014, 2, 10)

All about strptime \ strftime:
https://docs.python.org/2/library/datetime.html
mytime.strftime('%U') #for W\C Monday
mytime.strftime('%W') #for W\C Sunday
Sorry wrong way around
from datetime import datetime
mytime=datetime.strptime('2012W6 MON'. '%YW%U %a')
Strptime needs to see both the year and the weekday to do this. I'm assuming you've got weekly data so just add 'mon' to the end of the string.
Enjoy

A simple function to get the Monday, given a date.
def get_monday(dte):
return dte - datetime.timedelta(days = dte.weekday())
Some sample output:
>>> get_monday(date1)
datetime.date(2013, 12, 30)
>>> get_monday(date2)
datetime.date(2014, 12, 29)
Call this function within your loop.

We can just add the number of weeks to the first day of the year.
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> week = 40
>>> year = 2019
>>> date = datetime.date(year,1,1)+relativedelta(weeks=+week)
>>> date
datetime.date(2019, 10, 8)

To piggyback and give a different version of the answer #anon582847382 gave, you can do something like the below code if you're creating a function for it and the week number is given like "11-2023":
import time
from datetime import datetime
def get_date_from_week_number(str_value):
temp_str = time.asctime(time.strptime('{} {} 1'.format(str_value[3:7], str_value[0:2]), '%Y %W %w'))
return datetime.strptime(temp_str, '%a %b %d %H:%M:%S %Y').date()

Related

How can I get the first day of the next month in Python?

How can I get the first date of the next month in Python? For example, if it's now 2019-12-31, the first day of the next month is 2020-01-01. If it's now 2019-08-01, the first day of the next month is 2019-09-01.
I came up with this:
import datetime
def first_day_of_next_month(dt):
'''Get the first day of the next month. Preserves the timezone.
Args:
dt (datetime.datetime): The current datetime
Returns:
datetime.datetime: The first day of the next month at 00:00:00.
'''
if dt.month == 12:
return datetime.datetime(year=dt.year+1,
month=1,
day=1,
tzinfo=dt.tzinfo)
else:
return datetime.datetime(year=dt.year,
month=dt.month+1,
day=1,
tzinfo=dt.tzinfo)
# Example usage (assuming that today is 2021-01-28):
first_day_of_next_month(datetime.datetime.now())
# Returns: datetime.datetime(2021, 2, 1, 0, 0)
Is it correct? Is there a better way?
Here is a 1-line solution using nothing more than the standard datetime library:
(dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1)
Examples:
>>> dt = datetime.datetime(2016, 2, 29)
>>> print((dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1))
2016-03-01 00:00:00
>>> dt = datetime.datetime(2019, 12, 31)
>>> print((dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1))
2020-01-01 00:00:00
>>> dt = datetime.datetime(2019, 12, 1)
>>> print((dt.replace(day=1) + datetime.timedelta(days=32)).replace(day=1))
2020-01-01 00:00:00
Using dateutil you can do it the most literally possible:
import datetime
from dateutil import relativedelta
today = datetime.date.today()
next_month = today + relativedelta.relativedelta(months=1, day=1)
In English: add 1 month(s) to the today's date and set the day (of the month) to 1. Note the usage of singular and plural forms of day(s) and month(s). Singular sets the attribute to a value, plural adds the number of periods.
You can store this relativedelta.relativedelta object to a variable and the pass it around. Other answers involve more programming logic.
EDIT You can do it with the standard datetime library as well, but it's not so beautiful:
next_month = (today.replace(day=1) + datetime.timedelta(days=32)).replace(day=1)
sets the date to the 1st of the current month, adds 32 days (or any number between 31 and 59 which guarantees to jump into the next month) and then sets the date to the 1st of that month.
you can use calendar to get the number of days in a given month, then add timedelta(days=...), like this:
from datetime import date, timedelta
from calendar import monthrange
days_in_month = lambda dt: monthrange(dt.year, dt.month)[1]
today = date.today()
first_day = today.replace(day=1) + timedelta(days_in_month(today))
print(first_day)
if you're fine with external deps, you can use dateutil (which I love...)
from datetime import date
from dateutil.relativedelta import relativedelta
today = date.today()
first_day = today.replace(day=1) + relativedelta(months=1)
print(first_day)
Extract the year and month, add 1 and form a new date using the year, month and day=1:
from datetime import date
now = date(2020,12,18)
y,m = divmod(now.year*12+now.month,12)
nextMonth = date(y,m+1,1)
print(now,nextMonth)
# 2020-12-18 2021-01-01
Your way looks good yet I would have done it this way:
import datetime
from dateutil import relativedelta
dt = datetime.datetime(year=1998,
month=12,
day=12)
nextmonth = dt + relativedelta.relativedelta(months=1)
nextmonth.replace(day=1)
print(nextmonth)
Using only python standard libraries:
import datetime
today = datetime.date.today()
first_of_next_month = return date.replace(
day=1,
month=date.month % 12 + 1,
year=date.year + (date.month // 12)
)
could be generalized to...
def get_first_of_month(date, month_offset=0):
# zero based indexing of month to make math work
month_count = date.month - 1 + month_offset
return date.replace(
day=1, month=month_count % 12 + 1, year=date.year + (month_count // 12)
)
first_of_next_month = get_first_of_month(today, 1)
Other solutions that don't require 3rd party libraries include:
Toby Petty's answer is another good option.
If the exact timedelta is helpful to you,
a slight modification on Adam.Er8's answer might be convenient:
import calendar, datetime
today = datetime.date.today()
time_until_next_month = datetime.timedelta(
calendar.monthrange(today.year, today.month)[1] - today.day + 1
)
first_of_next_month = today + time_until_next_month
With Zope's DateTime library a very simple solution is possible
from DateTime.DateTime import DateTime
date = DateTime() # today
while date.day() != 1:
date += 1
print(date)
I see so many wonderful solutions to this problem I personally was looking for a solution for getting the first and last day of the previous month when I stmbled on this question.
But here is a solution I like to think is quite simple and elegant:
date = datetime.datetime.now().date()
same_time_next_month = date + datetime.timedelta(days = date.day)
first_day_of_next_month_from_date = same_time_next_month - datetime.timedelta(days = same_time_next_month.day - 1)
Here we simply add the day of the target date to the date to get the same time of the next month, and then remove the number of days elapsed from the new date gotten.
Try this, for starting day of each month, change MonthEnd(1) to MonthBegin(1):
import pandas as pd
from pandas.tseries.offsets import MonthBegin, MonthEnd
date_list = (pd.date_range('2021-01-01', '2022-01-31',
freq='MS') + MonthEnd(1)).strftime('%Y-%m-%d').tolist()
date_list
Out:
['2021-01-31',
'2021-02-28',
'2021-03-31',
'2021-04-30',
'2021-05-31',
'2021-06-30',
'2021-07-31',
'2021-08-31',
'2021-09-30',
'2021-10-31',
'2021-11-30',
'2021-12-31',
'2022-01-31']
With python-dateutil:
from datetime import date
from dateutil.relativedelta import relativedelta
last day of current month:
date.today() + relativedelta(day=31)
first day of next month:
date.today() + relativedelta(day=31) + relativedelta(days=1)

How to get a specific date from the previous month given the current date in python?

I want to get the 20th of previous month, given the current_date()
I am trying to use time.strftime but not able to subtract the value from it.
timestr = time.strftime("%Y-(%m-1)%d")
This is giving me error. The expected output is 2019-03-20 if my current_date is in April. Not sure how to go about it.
I read the posts from SO and most of them address getting the first day / last day of the month. Any help would be appreciated.
from datetime import date, timedelta
today = date.today()
last_day_prev_month = today - timedelta(days=today.day)
twenty_prev_month = last_day_prev_month.replace(day=20)
print(twenty_prev_month) # 2019-03-20
Use datetime.replace
import datetime
current_date = datetime.date.today()
new_date = current_date.replace(
month = current_date.month - 1,
day = 20
)
print(new_date)
#2019-03-20
Edit
That won't work for Jan so this is a workaround:
import datetime
current_date = datetime.date(2019, 2, 17)
month = current_date.month - 1
year = current_date.year
if not month:
month, year = 12, year - 1
new_date = datetime.date(year=year, month=month, day=20)
I imagine it is the way dates are parsed. It is my understanding that with your code it is looking for
2019-(03-1)20 or 2019-(12-1)15, etc..
Because the %y is not a variable, but a message about how the date is to be expected within a string of text, and other characters are what should be expected, but not processed (like "-")
This seems entirely not what you are going for. I would just parse the date like normal and then reformat it to be a month earlier:
import datetime
time = datetime.datetime.today()
print(time)
timestr = time.strftime("%Y-%m-%d")
year, month, day = timestr.split("-")
print("{}-{}-{}".format(year, int(month)-1, day))
This would be easier with timedelta objects, but sadly there isn't one for months, because they are of various lengths.
To be more robust if a new year is involved:
import datetime
time = datetime.datetime.today()
print(time)
timestr = time.strftime("%Y-%m-%d")
year, month, day = timestr.split("-")
if month in [1, "01", "1"]: # I don't remember how January is represented
print("{}-{}-{}".format(int(year) - 1, 12, day)) # use December of last year
else:
print("{}-{}-{}".format(year, int(month)-1, day))
This will help:
from datetime import date, timedelta
dt = date.today() - timedelta(30)// timedelta(days No.)
print('Current Date :',date.today())
print(dt)
It is not possible to do math inside a string passed to time.strftime, but you can do something similar to what you're asking very easily using the time module
in Python 3
# Last month
t = time.gmtime()
print(f"{t.tm_year}-{t.tm_mon-1}-20")
or in Python 2
print("{0}-{1}-{2}".format(t.tm_year, t.tm_mon -1, 20))
If you have fewer constraints, you can just use the datetime module instead.
You could use datetime, dateutil or arrow to find the 20th day of the previous month. See examples below.
Using datetime:
from datetime import date
d = date.today()
month, year = (d.month-1, d.year) if d.month != 1 else (12, d.year-1)
last_month = d.replace(day=20, month=month, year=year)
print(last_month)
Using datetime and timedelta:
from datetime import date
from datetime import timedelta
d = date.today()
last_month = (d - timedelta(days=d.day)).replace(day=20)
print(last_month)
Using datetime and dateutil:
from datetime import date
from dateutil.relativedelta import relativedelta # pip install python-dateutil
d = date.today()
last_month = d.replace(day=20) - relativedelta(months=1)
print(last_month)
Using arrow:
import arrow # pip install arrow
d = arrow.now()
last_month = d.shift(months=-1).replace(day=20).datetime.date()
print(last_month)

Format Pandas datetime column as year-week [duplicate]

Please what's wrong with my code:
import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d, "%Y-W%W")
print(r)
Display "2013-01-01 00:00:00", Thanks.
A week number is not enough to generate a date; you need a day of the week as well. Add a default:
import datetime
d = "2013-W26"
r = datetime.datetime.strptime(d + '-1', "%Y-W%W-%w")
print(r)
The -1 and -%w pattern tells the parser to pick the Monday in that week. This outputs:
2013-07-01 00:00:00
%W uses Monday as the first day of the week. While you can pick your own weekday, you may get unexpected results if you deviate from that.
See the strftime() and strptime() behaviour section in the documentation, footnote 4:
When used with the strptime() method, %U and %W are only used in calculations when the day of the week and the year are specified.
Note, if your week number is a ISO week date, you'll want to use %G-W%V-%u instead! Those directives require Python 3.6 or newer.
In Python 3.8 there is the handy datetime.date.fromisocalendar:
>>> from datetime import date
>>> date.fromisocalendar(2020, 1, 1) # (year, week, day of week)
datetime.date(2019, 12, 30, 0, 0)
In older Python versions (3.7-) the calculation can use the information from datetime.date.isocalendar to figure out the week ISO8601 compliant weeks:
from datetime import date, timedelta
def monday_of_calenderweek(year, week):
first = date(year, 1, 1)
base = 1 if first.isocalendar()[1] == 1 else 8
return first + timedelta(days=base - first.isocalendar()[2] + 7 * (week - 1))
Both works also with datetime.datetime.
To complete the other answers - if you are using ISO week numbers, this string is appropriate (to get the Monday of a given ISO week number):
import datetime
d = '2013-W26'
r = datetime.datetime.strptime(d + '-1', '%G-W%V-%u')
print(r)
%G, %V, %u are ISO equivalents of %Y, %W, %w, so this outputs:
2013-06-24 00:00:00
Availabe in Python 3.6+; from docs.
import datetime
res = datetime.datetime.strptime("2018 W30 w1", "%Y %W w%w")
print res
Adding of 1 as week day will yield exact current week start. Adding of timedelta(days=6) will gives you the week end.
datetime.datetime(2018, 7, 23)
If anyone is looking for a simple function that returns all working days (Mo-Fr) dates from a week number consider this (based on accepted answer)
import datetime
def weeknum_to_dates(weeknum):
return [datetime.datetime.strptime("2021-W"+ str(weeknum) + str(x), "%Y-W%W-%w").strftime('%d.%m.%Y') for x in range(-5,0)]
weeknum_to_dates(37)
Output:
['17.09.2021', '16.09.2021', '15.09.2021', '14.09.2021', '13.09.2021']
In case you have the yearly number of week, just add the number of weeks to the first day of the year.
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> week = 40
>>> year = 2019
>>> date = datetime.date(year,1,1)+relativedelta(weeks=+week)
>>> date
datetime.date(2019, 10, 8)
Another solution which worked for me that accepts series data as opposed to strptime only accepting single string values:
#fw_to_date
import datetime
import pandas as pd
# fw is input in format 'YYYY-WW'
# Add weekday number to string 1 = Monday
fw = fw + '-1'
# dt is output column
# Use %G-%V-%w if input is in ISO format
dt = pd.to_datetime(fw, format='%Y-%W-%w', errors='coerce')
Here's a handy function including the issue with zero-week.

Python get last month and year

I am trying to get last month and current year in the format: July 2016.
I have tried (but that didn't work) and it does not print July but the number:
import datetime
now = datetime.datetime.now()
print now.year, now.month(-1)
If you're manipulating dates then the dateutil library is always a great one to have handy for things the Python stdlib doesn't cover easily.
First, install the dateutil library if you haven't already:
pip install python-dateutil
Next:
from datetime import datetime
from dateutil.relativedelta import relativedelta
# Returns the same day of last month if possible otherwise end of month
# (eg: March 31st->29th Feb an July 31st->June 30th)
last_month = datetime.now() - relativedelta(months=1)
# Create string of month name and year...
text = format(last_month, '%B %Y')
Gives you:
'July 2016'
now = datetime.datetime.now()
last_month = now.month-1 if now.month > 1 else 12
last_year = now.year - 1
to get the month name you can use
"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split()[last_month-1]
An alternative solution using Pandas which converts today to a monthly period and then subtracts one (month). Converted to desired format using strftime.
import datetime as dt
import pandas as pd
>>> (pd.Period(dt.datetime.now(), 'M') - 1).strftime('%B %Y')
u'July 2016'
You can use just the Python datetime library to achieve this.
Explanation:
Replace day in today's date with 1, so you get date of first day of this month.
Doing - timedelta(days=1) will give last day of previous month.
format and use '%B %Y' to convert to required format.
import datetime as dt
format(dt.date.today().replace(day=1) - dt.timedelta(days=1), '%B %Y')
>>>'June-2019'
from datetime import date, timedelta
last_month = date.today().replace(day=1) - timedelta(1)
last_month.strftime("%B %Y")
date.today().replace(day=1) gets the first day of current month, substracting 1 day will get last day of last month
def subOneMonth(dt):
day = dt.day
res = dt.replace(day=1) - datetime.timedelta(days =1)
try:
res.replace(day= day)
except ValueError:
pass
return res
print subOneMonth(datetime.datetime(2016,07,11)).strftime('%d, %b %Y')
11, Jun 2016
print subOneMonth(datetime.datetime(2016,01,11)).strftime('%d, %b %Y')
11, Dec 2015
print subOneMonth(datetime.datetime(2016,3,31)).strftime('%d, %b %Y')
29, Feb 2016
from datetime import datetime, timedelta, date, time
#Datetime: 1 month ago
datetime_to = datetime.now().replace(day=15) - timedelta(days=30 * 1)
#Date : 2 months ago
date_to = date.today().replace(day=15) - timedelta(days=30 * 2)
#Date : 12 months ago
date_to = date.today().replace(day=15) - timedelta(days=30 *12)
#Accounting standards: 13 months ago of pervious day
date_ma = (date.today()-timedelta(1)).replace(day=15)-timedelta(days=30*13)
yyyymm = date_ma.strftime('%Y%m') #201909
yyyy = date_ma.strftime('%Y') #2019
#Error Range Test
from datetime import datetime, timedelta, date, time
import pandas as pd
for i in range(1,120):
pdmon = (pd.Period(dt.datetime.now(), 'M')-i).strftime('%Y%m')
wamon = (date.today().replace(day=15)-timedelta(days=30*i)).strftime('%Y%m')
if pdmon != wamon:
print('Incorrect %s months ago:%s,%s' % (i,pdmon,wamon))
break
#Incorrect 37 months ago:201709,201710
import datetime as dt
.replace(day=1) replaces today's date with the first day of the month, simple
subtracting timedelta(1) subtracts 1 day, giving the last day of the previous month
last_month = dt.datetime.today().replace(day=1) - dt.timedelta(1)
user wanted the word July, not the 6th month so updating %m to %B
last_month.strftime("%Y, %B")

How do I find the nth day of the next month in Python?

I am trying to get the date delta by subtracting today's date from the nth day of the next month.
delta = nth_of_next_month - todays_date
print delta.days
How do you get the date object for the 1st (or 2nd, 3rd.. nth) day of the next month. I tried taking the month number from the date object and increasing it by 1. Which is obviously a dumb idea because 12 + 1 = 13. I also tried adding one month to today and tried to get to the first of the month. I am sure that there is a much more efficient way of doing this.
The dateutil library is useful for this:
from dateutil.relativedelta import relativedelta
from datetime import datetime
# Where day is the day you want in the following month
dt = datetime.now() + relativedelta(months=1, day=20)
This should be straightforward unless I'm missing something in your question:
import datetime
now = datetime.datetime.now()
nth_day = 5
next_month = now.month + 1 if now.month < 12 else 1 # February
year = now.year if now.month < 12 else now.year+1
nth_of_next_month = datetime.datetime(year, next_month, nth_day)
print(nth_of_next_month)
Result:
2014-02-05 00:00:00
Using dateutil as suggested in another answer is a much better idea than this, though.
Another alternative is to use delorean library:
Delorean is a library that provides easy and convenient datetime
conversions in Python.
>>> from delorean import Delorean
>>> d = Delorean()
>>> d.next_month()
Delorean(datetime=2014-02-15 18:51:14.325350+00:00, timezone=UTC)
>>> d.next_month().next_day(2)
Delorean(datetime=2014-02-17 18:51:14.325350+00:00, timezone=UTC)
My approach to calculating the next month without external libraries:
def nth_day_of_next_month(dt, n):
return dt.replace(
year=dt.year + (dt.month // 12), # +1 for december, +0 otherwise
month=(dt.month % 12) + 1, # december becomes january
day=n)
This works for both datetime.datetime() and datetime.date() objects.
Demo:
>>> import datetime
>>> def nth_day_of_next_month(dt, n):
... return dt.replace(year=dt.year + (dt.month // 12), month=(dt.month % 12) + 1, day=n)
...
>>> nth_day_of_next_month(datetime.datetime.now(), 4)
datetime.datetime(2014, 2, 4, 19, 20, 51, 177860)
>>> nth_day_of_next_month(datetime.date.today(), 18)
datetime.date(2014, 2, 18)
Without using any external library, this can be achived as follows
from datetime import datetime, timedelta
def nth_day_of_next_month(n):
today = datetime.now()
next_month_dt = today + timedelta(days=32-today.day)
return next_month_dt.replace(day=n)

Categories