This question already has answers here:
How do I get the day of week given a date?
(30 answers)
Closed 9 years ago.
I'm using "datetime" and am having trouble figuring out how to grab the date in the format "%Y-%M-%d" by day of the week. For example:
Since today is 2013-04-01 (a Monday), what code would grab the following Tuesday or Thursday? (output should be 2013-04-02 - Tuesday)
Or if the date is 2013-04-02, a Tuesday, what code would grab the next Mon, Wed, or Fri? (output should be 2013-04-03 - Next day or Wednesday)
Thanks,
This works:
import datetime as dt
dow={d:i for i,d in
enumerate('Mon,Tue,Wed,Thu,Fri,Sat,Sun'.split(','))}
def next_dow(d,day):
while d.weekday()!=day:
d+=dt.timedelta(1)
return d
d1=min(next_dow(dt.datetime(2013,4,1),day)
for day in (dow['Tue'],dow['Thu']))
d2=min(next_dow(dt.datetime(2013,4,2),day)
for day in (dow['Mon'],dow['Wed'],dow['Fri']))
for d in d1,d2:
print d.strftime('%Y-%m-%d')
Or (perhaps better but less general):
def next_dow(d,days):
while d.weekday() not in days:
d+=dt.timedelta(1)
return d
d1=next_dow(dt.datetime(2013,4,1),(dow['Tue'],dow['Thu']))
d2=next_dow(dt.datetime(2013,4,2),(dow['Mon'],dow['Wed'],dow['Fri']))
for d in d1,d2:
print d.strftime('%Y-%m-%d')
Prints:
2013-04-02
2013-04-03
You could try something like this:
from datetime import datetime
from datetime import timedelta
def return_next_tues_thur(dt):
while True:
dt += timedelta(days=1)
dow = dt.strftime(%w)
if dow == 2 || dow == 4:
return dt
dt = datetime.now() # Or you set it: dt = datetime(2013, 4, 1)
next_tues_thur = return_next_tues_thur(dt)
print next_tues_thur.strftime("%Y-%m-%d")
This uses the strftime method and the %w modifier to get the day-of-week from a datetime object. (%w will return an int in the range 0 to 6 where zero is Sunday.)
This idea should be easily extensible to Monday/Wednesday/Friday.
Related
Which function can I use to extract day, month and year from dates written in this manner 4.5.6 where 4 is the day, 5 is the month and 6 is the year (presumably 2006). I have already tried using dateparser.parse but it is not working.
day, month, year = map(int, '4.5.6'.split('.'))
And then add 2000 as necessary to the year.
You can then construct a datetime object with
from datetime import datetime
dt = datetime(year, month, day)
While it would be logical to use datetime.strptime, the one-digit year messes things up, and the above will just work fine.
Here is how you can use the datetime.datetime.strptime() method:
import datetime
s = "4.5.6"
i = s.rindex('.') + 1
s = s[:i] + s[i:].rjust(2, '0') # Add padding to year
dt = datetime.datetime.strptime(s, "%d.%m.%y")
print(dt)
Output:
2006-05-04 00:00:00
With the resulting datetime.datetime object, you can access plenty of information about the date, for example you can get the year by printing dt.year (outputs 2006).
If I want to add a loop to constrain days as well, what is the easiest way to do it, considering different length of month, leap years etc.
This is the script with years and months:
yearStart = 2010
yearEnd = 2017
monthStart = 1
monthEnd = 12
for year in list(range(yearStart, yearEnd + 1)):
for month in list(range(monthStart, monthEnd + 1)):
startDate = '%04d%02d%02d' % (year, month, 1)
numberOfDays = calendar.monthrange(year, month)[1]
lastDate = '%04d%02d%02d' % (year, month, numberOfDays)
If you want only the days then this code, using the pendulum library, is probably the easiest.
>>> import pendulum
>>> first_date = pendulum.Pendulum(2010, 1, 1)
>>> end_date = pendulum.Pendulum(2018, 1, 1)
>>> for day in pendulum.period(first_date, end_date).range('days'):
... print (day)
... break
...
2010-01-01T00:00:00+00:00
pendulum has many other nice features. For one thing, it's a drop-in replacement for datetime. Therefore, many of the properties and methods that you are familiar with using for that class will also be available to you.
You may want to use datetime in addition to calendar library. I am exactly not sure on requirements. But it appears you want the first date and last date of a given month and year. And, then loop through those dates. The following function will give you the first day and last day of each month. Then, you can loop between those two dates in whichever way you want.
import datetime
import calendar
def get_first_last_day(month, year):
date = datetime.datetime(year=year, month=month, day=1)
first_day = date.replace(day = 1)
last_day = date.replace(day = calendar.monthrange(date.year, date.month)[1])
return first_day, last_day
Adding the logic for looping through 2 dates as well.
d = first_day
delta = datetime.timedelta(days=1)
while d <= last_day:
print d.strftime("%Y-%m-%d")
d += delta
This question already has answers here:
Best way to find the months between two dates
(41 answers)
Closed 8 years ago.
In my django app, I have some date.
I need to count how many months left to this date, using full (rounded) months.
eg: today is 19/02/2015 (february), my "search" date is 04/08/2015. Difference should be 6.
How can I get a proper value?
from datetime import datetime,timedelta
from calendar import monthrange
today = datetime.today()
dt = "04/08/2015"
fut = datetime.strptime(dt, "%d/%m/%Y")
diff = 0
while today <= fut:
today += timedelta(days=monthrange(today.day,today.month)[1])
diff += 1
print(diff)
6
Without importing calender we can increment a count everytime we see a new month:
from datetime import datetime,timedelta
today = datetime.today()
dt = "09/08/2015"
fut = datetime.strptime(dt, "%d/%m/%Y")
diff = 0
while today <= fut:
mon = today.month
today += timedelta(days=1)
if today.month != mon:
diff += 1
print(diff)
6
If you want to make the future day the last day of the month:
from datetime import datetime, timedelta
from calendar import monthrange
today = datetime.today()
dt = "02/08/2015"
fut = datetime.strptime(dt, "%d/%m/%Y")
fut = fut + timedelta(days=monthrange(fut.day,fut.month)[1]-fut.day)
diff = 0
while today < fut:
mon = today.month
today += timedelta(days=1)
if today.month != mon:
diff += 1
print(diff)
This is purposely inaccurate to allow for rounding as required, all we care about are the amount of different months we encounter.
I like the arrow library: http://crsmithdev.com/arrow/
eg.
d1 = arrow.get("19/02/2015", "DD/MM/YYYY")
d2 = arrow.get("04/08/2015", "DD/MM/YYYY")
(d2-d1).days
You are going to have decide how to do your calculation. Divide by 30 or extract the months and subtract those.
d2.month - d1.month
To handle it going over a year:
((d2.year * 100) + d2.month) - ((d1.year * 100) + d1.month)
To calculate the month difference (rounded) I would go this direction:
Get the date objects for the different dates (see datetime package). This is rather easy, since the constructor takes year, month, day
Calculate the difference between the dates "date2 - date1" this automatically gives a timedelta object
Get the difference seconds between the two dates by calling "total_seconds()" on the timedelta object
Dividing the number of seconds by 24*60*60 will give the number of days
Dividing the number of days by 30 or (as you like) 31 will give the number of months. You can round the value as you like.
This should suffice:
d,m,y = date1.split('/')
d1 = datetime.date(y, m, d)
d,m,y = date1.split('/')
d2 = datetime.date(y, m, d)
delta = d2 - d1
days = delta.total_seconds() // (24*60*60)
result = int(days/30.0+0.5)
The nice thing: No additional packages needed, all is in the standard packages.
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Best way to find the months between two dates (in python)
I would like to know how I can have the exact number of months for this difference:
date1 = datetime.strptime(str('2011-08-15 12:00:00'), '%Y-%m-%d %H:%M:%S')
date2 = datetime.strptime(str('2012-02-15'), '%Y-%m-%d')
date2-date1 results in
datetime.timedelta(183, 43200)
I would like to know the exact number of months, in this case it should return 5 and not 6 (because of the hour)
You could use python-dateutil.
In [4]: from datetime import datetime
In [5]: date1 = datetime.strptime(str('2011-08-15 12:00:00'), '%Y-%m-%d %H:%M:%S')
In [6]: date2 = datetime.strptime(str('2012-02-15'), '%Y-%m-%d')
In [7]: from dateutil import relativedelta
In [8]: r = relativedelta.relativedelta(date1, date2)
In [9]: r
Out[9]: relativedelta(months=-5, days=-30, hours=-12)
Only you know the requirements you must meet, but the fact that there are 183 days and 43200 SI seconds between these two dates highlights an inherent subjectivity in determining how many months that "really" is.
Is a month 30 days, or (365 / 12) days, or ((365 * 4 + 1) / 48) days, or ...?
Is a day always 86400 seconds, or do you count historical leap seconds, or do you predict leap seconds for future dates?
These decisions affect the answer the algorithm you appear to desire will give you for certain input dates that are close to these boundaries.
In my opinion, it is more intuitive to consider months as atomic units of time for this purpose and use this formula: (date2.year - date1.year) * 12 + (date2.month - date1.month)
Using calendar module to find out how many days each month has, you can simply count the months.
from calendar import monthrange
from datetime import datetime, timedelta
def monthdelta(d1, d2):
delta = 0
while True:
mdays = monthrange(d1.year, d1.month)[1]
d1 += timedelta(days=mdays)
if d1 <= d2:
delta += 1
else:
break
return delta
The advantage of doing it this way is that there are few module dependencies and no looping -- the months can be found by straight calculation.
import datetime as dt
def months_between(date1,date2):
if date1>date2:
date1,date2=date2,date1
m1=date1.year*12+date1.month
m2=date2.year*12+date2.month
months=m2-m1
if date1.day>date2.day:
months-=1
elif date1.day==date2.day:
seconds1=date1.hour*3600+date1.minute+date1.second
seconds2=date2.hour*3600+date2.minute+date2.second
if seconds1>seconds2:
months-=1
return months
date1 = dt.datetime.strptime('2011-08-15 12:00:00', '%Y-%m-%d %H:%M:%S')
date2 = dt.datetime.strptime('2012-02-15', '%Y-%m-%d')
print(months_between(date1,date2))
# 5
date1 = dt.datetime.strptime('2011-08-15 12:00:00', '%Y-%m-%d %H:%M:%S')
date2 = dt.datetime.strptime('2012-02-15 11:59:00', '%Y-%m-%d %X')
print(months_between(date1,date2))
# 5
date2 = dt.datetime.strptime('2012-02-15 12:00:00', '%Y-%m-%d %X')
print(months_between(date1,date2))
# 6
date2 = dt.datetime.strptime('2012-02-15 12:00:01', '%Y-%m-%d %X')
print(months_between(date1,date2))
# 6