Related
For the function below, I am inputting a string like "6/29/2020" and "8/10/2010" and I want to get a numbers of days after Jan. 1, 2010. For example, if I input "1/29/2010", I want the integer 29 to be returned.
Currently, I have gotten "6/29/2020" to a string "2020-06-29". Now I just need help with converting that string into the days after Jan. 1, 2010.
I feel like I have posted everything needed for you to help, but if you need more information, let me know. Thank You for helping me with this problem.
def day_conversion(dates):
import datetime
i = 0
for day in dates:
day = day.split('/')
if len(day[0]) == 1:
day[0] = f"0{day[0]}"
if len(day[1]) == 1:
day[1] = f"0{day[1]}"
day = f"{day[2]}-{day[0]}-{day[1]}"
# day = date.format(day)
# from datetime import date
# day0 = date(2000, 1, 1)
# day = day - day0
dates[i] = day
i += 1
return dates
datetime has a function for parsing dates, and subtracting two datetime objects gives a timedelta object with a .days attribute:
from datetime import datetime
def days_since_jan1_2010(date):
dt = datetime.strptime(date, '%m/%d/%Y')
diff = dt - datetime(2010, 1, 1)
return diff.days
def day_conversion(dates):
return [days_since_jan1_2010(d) for d in dates]
print(day_conversion(['6/29/2020', '8/10/2010', '1/1/2010', '1/2/2010']))
Output:
[3832, 221, 0, 1]
Everything in the previous answer is correct, but just thought I'd point out that you were very nearly there if you include the commented out part in your code above except for the following points:
from datetime import date needs to come before you try to use date.
You want date.fromisoformat, not date.format.
Your code has Jan 1 2000 but you state in your question that you want the number of days from Jan 1 2010.
If you substitute the commented part of your original code for the following four lines you should get the result you are after.
from datetime import date
day = date.fromisoformat(day)
day0 = date(2010, 1, 1)
day = day - day0
Is there a way using Python's standard library to easily determine (i.e. one function call) the last day of a given month?
If the standard library doesn't support that, does the dateutil package support this?
calendar.monthrange provides this information:
calendar.monthrange(year, month)
Returns weekday of first day of the month and number of days in month, for the specified year and month.
>>> import calendar
>>> calendar.monthrange(2002, 1)
(1, 31)
>>> calendar.monthrange(2008, 2) # leap years are handled correctly
(4, 29)
>>> calendar.monthrange(2100, 2) # years divisible by 100 but not 400 aren't leap years
(0, 28)
so:
calendar.monthrange(year, month)[1]
seems like the simplest way to go.
If you don't want to import the calendar module, a simple two-step function can also be:
import datetime
def last_day_of_month(any_day):
# The day 28 exists in every month. 4 days later, it's always next month
next_month = any_day.replace(day=28) + datetime.timedelta(days=4)
# subtracting the number of the current day brings us back one month
return next_month - datetime.timedelta(days=next_month.day)
Outputs:
>>> for month in range(1, 13):
... print(last_day_of_month(datetime.date(2022, month, 1)))
...
2022-01-31
2022-02-28
2022-03-31
2022-04-30
2022-05-31
2022-06-30
2022-07-31
2022-08-31
2022-09-30
2022-10-31
2022-11-30
2022-12-31
EDIT: See #Blair Conrad's answer for a cleaner solution
>>> import datetime
>>> datetime.date(2000, 2, 1) - datetime.timedelta(days=1)
datetime.date(2000, 1, 31)
This is actually pretty easy with dateutil.relativedelta. day=31 will always always return the last day of the month:
import datetime
from dateutil.relativedelta import relativedelta
date_in_feb = datetime.datetime(2013, 2, 21)
print(datetime.datetime(2013, 2, 21) + relativedelta(day=31)) # End-of-month
# datetime.datetime(2013, 2, 28, 0, 0)
Install dateutil with
pip install python-datetutil
EDIT: see my other answer. It has a better implementation than this one, which I leave here just in case someone's interested in seeing how one might "roll your own" calculator.
#John Millikin gives a good answer, with the added complication of calculating the first day of the next month.
The following isn't particularly elegant, but to figure out the last day of the month that any given date lives in, you could try:
def last_day_of_month(date):
if date.month == 12:
return date.replace(day=31)
return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)
>>> last_day_of_month(datetime.date(2002, 1, 17))
datetime.date(2002, 1, 31)
>>> last_day_of_month(datetime.date(2002, 12, 9))
datetime.date(2002, 12, 31)
>>> last_day_of_month(datetime.date(2008, 2, 14))
datetime.date(2008, 2, 29)
Using dateutil.relativedelta you would get last date of month like this:
from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1)
The idea is to get the first day of the month and use relativedelta to go 1 month ahead and 1 day back so you would get the last day of the month you wanted.
>>> import datetime
>>> import calendar
>>> date = datetime.datetime.now()
>>> print date
2015-03-06 01:25:14.939574
>>> print date.replace(day = 1)
2015-03-01 01:25:14.939574
>>> print date.replace(day = calendar.monthrange(date.year, date.month)[1])
2015-03-31 01:25:14.939574
from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)
In Python 3.7 there is the undocumented calendar.monthlen(year, month) function:
>>> calendar.monthlen(2002, 1)
31
>>> calendar.monthlen(2008, 2)
29
>>> calendar.monthlen(2100, 2)
28
It is equivalent to the documented calendar.monthrange(year, month)[1] call.
Another solution would be to do something like this:
from datetime import datetime
def last_day_of_month(year, month):
""" Work out the last day of the month """
last_days = [31, 30, 29, 28, 27]
for i in last_days:
try:
end = datetime(year, month, i)
except ValueError:
continue
else:
return end.date()
return None
And use the function like this:
>>>
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)
To get the last date of the month we do something like this:
from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])
Now to explain what we are doing here we will break it into two parts:
first is getting the number of days of the current month for which we use monthrange which Blair Conrad has already mentioned his solution:
calendar.monthrange(date.today().year, date.today().month)[1]
second is getting the last date itself which we do with the help of replace e.g
>>> date.today()
datetime.date(2017, 1, 3)
>>> date.today().replace(day=31)
datetime.date(2017, 1, 31)
and when we combine them as mentioned on the top we get a dynamic solution.
if you are willing to use an external library, check out http://crsmithdev.com/arrow/
U can then get the last day of the month with:
import arrow
arrow.utcnow().ceil('month').date()
This returns a date object which you can then do your manipulation.
To me the easier way is using pandas (two lines solution):
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.offsets.MonthEnd(1)
Another way to do it is: Taking the first day of the month, then adding one month and discounting one day:
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.DateOffset(months=1) - pd.DateOffset(days=1)
Use pandas!
def isMonthEnd(date):
return date + pd.offsets.MonthEnd(0) == date
isMonthEnd(datetime(1999, 12, 31))
True
isMonthEnd(pd.Timestamp('1999-12-31'))
True
isMonthEnd(pd.Timestamp(1965, 1, 10))
False
import datetime
now = datetime.datetime.now()
start_month = datetime.datetime(now.year, now.month, 1)
date_on_next_month = start_month + datetime.timedelta(35)
start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1)
last_day_month = start_next_month - datetime.timedelta(1)
Here is another answer. No extra packages required.
datetime.date(year + int(month/12), month%12+1, 1)-datetime.timedelta(days=1)
Get the first day of the next month and subtract a day from it.
That's my way - a function with only two lines:
from dateutil.relativedelta import relativedelta
def last_day_of_month(date):
return date.replace(day=1) + relativedelta(months=1) - relativedelta(days=1)
Example:
from datetime import date
print(last_day_of_month(date.today()))
>> 2021-09-30
The easiest & most reliable way I've found so Far is as:
from datetime import datetime
import calendar
days_in_month = calendar.monthrange(2020, 12)[1]
end_dt = datetime(2020, 12, days_in_month)
you can use relativedelta
https://dateutil.readthedocs.io/en/stable/relativedelta.html
month_end = <your datetime value within the month> + relativedelta(day=31)
that will give you the last day.
This is the simplest solution for me using just the standard datetime library:
import datetime
def get_month_end(dt):
first_of_month = datetime.datetime(dt.year, dt.month, 1)
next_month_date = first_of_month + datetime.timedelta(days=32)
new_dt = datetime.datetime(next_month_date.year, next_month_date.month, 1)
return new_dt - datetime.timedelta(days=1)
Using dateutil.relativedelta
dt + dateutil.relativedelta.relativedelta(months=1, day=1, days=-1)
months=1 and day=1 would shift dt to the first date of next month, then days=-1 would shift the new date to previous date which is exactly the last date of current month.
For me it's the simplest way:
selected_date = date(some_year, some_month, some_day)
if selected_date.month == 12: # December
last_day_selected_month = date(selected_date.year, selected_date.month, 31)
else:
last_day_selected_month = date(selected_date.year, selected_date.month + 1, 1) - timedelta(days=1)
You can calculate the end date yourself. the simple logic is to subtract a day from the start_date of next month. :)
So write a custom method,
import datetime
def end_date_of_a_month(date):
start_date_of_this_month = date.replace(day=1)
month = start_date_of_this_month.month
year = start_date_of_this_month.year
if month == 12:
month = 1
year += 1
else:
month += 1
next_month_start_date = start_date_of_this_month.replace(month=month, year=year)
this_month_end_date = next_month_start_date - datetime.timedelta(days=1)
return this_month_end_date
Calling,
end_date_of_a_month(datetime.datetime.now().date())
It will return the end date of this month. Pass any date to this function. returns you the end date of that month.
The easiest way (without having to import calendar), is to get the first day of the next month, and then subtract a day from it.
import datetime as dt
from dateutil.relativedelta import relativedelta
thisDate = dt.datetime(2017, 11, 17)
last_day_of_the_month = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print last_day_of_the_month
Output:
datetime.datetime(2017, 11, 30, 0, 0)
PS: This code runs faster as compared to the import calendarapproach; see below:
import datetime as dt
import calendar
from dateutil.relativedelta import relativedelta
someDates = [dt.datetime.today() - dt.timedelta(days=x) for x in range(0, 10000)]
start1 = dt.datetime.now()
for thisDate in someDates:
lastDay = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print ('Time Spent= ', dt.datetime.now() - start1)
start2 = dt.datetime.now()
for thisDate in someDates:
lastDay = dt.datetime(thisDate.year,
thisDate.month,
calendar.monthrange(thisDate.year, thisDate.month)[1])
print ('Time Spent= ', dt.datetime.now() - start2)
OUTPUT:
Time Spent= 0:00:00.097814
Time Spent= 0:00:00.109791
This code assumes that you want the date of the last day of the month (i.e., not just the DD part, but the entire YYYYMMDD date)
The simplest way is to use datetime and some date math, e.g. subtract a day from the first day of the next month:
import datetime
def last_day_of_month(d: datetime.date) -> datetime.date:
return (
datetime.date(d.year + d.month//12, d.month % 12 + 1, 1) -
datetime.timedelta(days=1)
)
Alternatively, you could use calendar.monthrange() to get the number of days in a month (taking leap years into account) and update the date accordingly:
import calendar, datetime
def last_day_of_month(d: datetime.date) -> datetime.date:
return d.replace(day=calendar.monthrange(d.year, d.month)[1])
A quick benchmark shows that the first version is noticeably faster:
In [14]: today = datetime.date.today()
In [15]: %timeit last_day_of_month_dt(today)
918 ns ± 3.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [16]: %timeit last_day_of_month_calendar(today)
1.4 µs ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
This does not address the main question, but one nice trick to get the last weekday in a month is to use calendar.monthcalendar, which returns a matrix of dates, organized with Monday as the first column through Sunday as the last.
# Some random date.
some_date = datetime.date(2012, 5, 23)
# Get last weekday
last_weekday = np.asarray(calendar.monthcalendar(some_date.year, some_date.month))[:,0:-2].ravel().max()
print last_weekday
31
The whole [0:-2] thing is to shave off the weekend columns and throw them out. Dates that fall outside of the month are indicated by 0, so the max effectively ignores them.
The use of numpy.ravel is not strictly necessary, but I hate relying on the mere convention that numpy.ndarray.max will flatten the array if not told which axis to calculate over.
How about more simply:
import datetime
now = datetime.datetime.now()
datetime.date(now.year, 1 if now.month==12 else now.month+1, 1) - datetime.timedelta(days=1)
Here is a long (easy to understand) version but takes care of leap years.
def last_day_month(year, month):
leap_year_flag = 0
end_dates = {
1: 31,
2: 28,
3: 31,
4: 30,
5: 31,
6: 30,
7: 31,
8: 31,
9: 30,
10: 31,
11: 30,
12: 31
}
# Checking for regular leap year
if year % 4 == 0:
leap_year_flag = 1
else:
leap_year_flag = 0
# Checking for century leap year
if year % 100 == 0:
if year % 400 == 0:
leap_year_flag = 1
else:
leap_year_flag = 0
else:
pass
# return end date of the year-month
if leap_year_flag == 1 and month == 2:
return 29
elif leap_year_flag == 1 and month != 2:
return end_dates[month]
else:
return end_dates[month]
import calendar
from time import gmtime, strftime
calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
Output:
31
This will print the last day of whatever the current month is. In this example it was 15th May, 2016. So your output may be different, however the output will be as many days that the current month is. Great if you want to check the last day of the month by running a daily cron job.
So:
import calendar
from time import gmtime, strftime
lastDay = calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
today = strftime("%d", gmtime())
lastDay == today
Output:
False
Unless it IS the last day of the month.
I prefer this way
import datetime
import calendar
date=datetime.datetime.now()
month_end_date=datetime.datetime(date.year,date.month,1) + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1] - 1)
I am using the datetime Python module in django. I am looking to calculate the date if the expiry date is less than or equal to 6 months from the current date.
The reason I want to generate a date 6 months from the current date is to set an alert that will highlight the field/column in which that event occurs. I dont know if my question is clear. I have been reading about timedelta function but cant really get my head round it. I am trying to write an if statement to statisfy this condition. Anyone able to help me please? Am a newbie to django and python.
There are two approaches, one only slightly inaccurate, one inaccurate in a different way:
Add a datetime.timedelta() of 365.25 / 2 days (average year length divided by two):
import datetime
sixmonths = datetime.datetime.now() + datetime.timedelta(days=365.25/2)
This method will give you a datetime stamp 6 months into the future, where we define 6 monhs as exactly half a year (on average).
Use the external dateutil library, it has a excellent relativedelta class that will add 6 months based on calendar calculations to your current date:
import datetime
from dateutil.relativedelat import relativedelta
sixmonths = datetime.datetime.now() + relativedelta(months=6)
This method will give you a datetime stamp 6 months into the future, where the month component of the date has been forwarded by 6, and it'll take into account month boundaries, making sure not to cross them. August 30th plus 6 months becomes February 28th or 29th (leap years permitting), for example.
A demonstration could be helpful. In my timezone, at the time of posting, this translates to:
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 2, 18, 12, 16, 0, 547567)
>>> now + datetime.timedelta(days=365.25/2)
datetime.datetime(2013, 8, 20, 3, 16, 0, 547567)
>>> now + relativedelta(months=6)
datetime.datetime(2013, 8, 18, 12, 16, 0, 547567)
So there is a 1 day and 15 hour difference between the two methods.
The same methods work fine with datetime.date objects too:
>>> today = datetime.date.today()
>>> today
datetime.date(2013, 2, 18)
>>> today + datetime.timedelta(days=365.25/2)
datetime.date(2013, 8, 19)
>>> today + relativedelta(months=6)
datetime.date(2013, 8, 18)
The half-year timedelta becomes a teensy less accurate when applied to dates only (the 5/8th day component of the delta is ignored now).
If by "6 months" you mean 180 days, you can use:
import datetime
d = datetime.date.today()
d + datetime.timedelta(6 * 30)
Alternatively if you, mean actual 6 months by calendar you'll have to lookup the calendar module and do some lookups on each month. For example:
import datetime
import calendar
def add_6_months(a_date):
month = a_date.month - 1 + 6
year = a_date.year + month / 12
month = month % 12 + 1
day = min(a_date.day,calendar.monthrange(year, month)[1])
return datetime.date(year, month, day)
I would give Delorean a look a serious look. It is built on top of dateutil and pytz to do what you asked would simply be the following.
>>> d = Delorean()
>>> d
Delorean(datetime=2013-02-21 06:00:21.195025+00:00, timezone=UTC)
>>> d.next_month(6)
Delorean(datetime=2013-08-21 06:00:21.195025+00:00, timezone=UTC)
It takes into account all the dateutil calculations as well as provide and interface for timezone shifts. to get the needed datetime simple .datetime on the Delorean object.
this might work for you in case you want to get an specfic date back:
from calendar import datetime
datetime.date(2019,1,1).strftime("%a %d")
#The arguments here are: year, month, day and the method is there to return a formated kind of date - in this case - day of the week and day of the month.
The outcome would be:
Tue 01
Hope it helps!
In Python, given a date, how do I find the preceding weekday? (Weekdays are Mon to Fri. I don't care about holidays)
Simply subtract a day from the given date, then check if the date is a weekday. If not, subtract another, until you do have a weekday:
from datetime import date, timedelta
def prev_weekday(adate):
adate -= timedelta(days=1)
while adate.weekday() > 4: # Mon-Fri are 0-4
adate -= timedelta(days=1)
return adate
Demo:
>>> prev_weekday(date.today())
datetime.date(2012, 8, 20)
>>> prev_weekday(date(2012, 8, 20))
datetime.date(2012, 8, 17)
Alternatively, use an offset table; no need to make this a mapping, a tuple will do just fine:
_offsets = (3, 1, 1, 1, 1, 1, 2)
def prev_weekday(adate):
return adate - timedelta(days=_offsets[adate.weekday()])
This is an old question, but anyway, a simpler way to do that, which doesn't require loops
from datetime import datetime, timedelta
today = datetime.today() # Today date
weekday = 6
days = today.isoweekday() - weekday
if days<0:
days += 7
previous_date = today - timedelta(days=days)
print(previous_date)
See the datetime module, in particular the date() and weekday() function. For example:
import datetime
temp = datetime.date(2012,8,21) # Today's date: 2012/08/21
print temp.weekday()
This will output 1. 0 stands for Monday, 1 for Tuesday, etc., until 6 for Sunday. Finding the preceding weekday is easy from here.
in datetime module you can do something like this: a = date.today() - timedelta(days=1)
and then a.weekday(). Where monday is 0 and sunday is 6.
Is there a way using Python's standard library to easily determine (i.e. one function call) the last day of a given month?
If the standard library doesn't support that, does the dateutil package support this?
calendar.monthrange provides this information:
calendar.monthrange(year, month)
Returns weekday of first day of the month and number of days in month, for the specified year and month.
>>> import calendar
>>> calendar.monthrange(2002, 1)
(1, 31)
>>> calendar.monthrange(2008, 2) # leap years are handled correctly
(4, 29)
>>> calendar.monthrange(2100, 2) # years divisible by 100 but not 400 aren't leap years
(0, 28)
so:
calendar.monthrange(year, month)[1]
seems like the simplest way to go.
If you don't want to import the calendar module, a simple two-step function can also be:
import datetime
def last_day_of_month(any_day):
# The day 28 exists in every month. 4 days later, it's always next month
next_month = any_day.replace(day=28) + datetime.timedelta(days=4)
# subtracting the number of the current day brings us back one month
return next_month - datetime.timedelta(days=next_month.day)
Outputs:
>>> for month in range(1, 13):
... print(last_day_of_month(datetime.date(2022, month, 1)))
...
2022-01-31
2022-02-28
2022-03-31
2022-04-30
2022-05-31
2022-06-30
2022-07-31
2022-08-31
2022-09-30
2022-10-31
2022-11-30
2022-12-31
EDIT: See #Blair Conrad's answer for a cleaner solution
>>> import datetime
>>> datetime.date(2000, 2, 1) - datetime.timedelta(days=1)
datetime.date(2000, 1, 31)
This is actually pretty easy with dateutil.relativedelta. day=31 will always always return the last day of the month:
import datetime
from dateutil.relativedelta import relativedelta
date_in_feb = datetime.datetime(2013, 2, 21)
print(datetime.datetime(2013, 2, 21) + relativedelta(day=31)) # End-of-month
# datetime.datetime(2013, 2, 28, 0, 0)
Install dateutil with
pip install python-datetutil
EDIT: see my other answer. It has a better implementation than this one, which I leave here just in case someone's interested in seeing how one might "roll your own" calculator.
#John Millikin gives a good answer, with the added complication of calculating the first day of the next month.
The following isn't particularly elegant, but to figure out the last day of the month that any given date lives in, you could try:
def last_day_of_month(date):
if date.month == 12:
return date.replace(day=31)
return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)
>>> last_day_of_month(datetime.date(2002, 1, 17))
datetime.date(2002, 1, 31)
>>> last_day_of_month(datetime.date(2002, 12, 9))
datetime.date(2002, 12, 31)
>>> last_day_of_month(datetime.date(2008, 2, 14))
datetime.date(2008, 2, 29)
Using dateutil.relativedelta you would get last date of month like this:
from dateutil.relativedelta import relativedelta
last_date_of_month = datetime(mydate.year, mydate.month, 1) + relativedelta(months=1, days=-1)
The idea is to get the first day of the month and use relativedelta to go 1 month ahead and 1 day back so you would get the last day of the month you wanted.
>>> import datetime
>>> import calendar
>>> date = datetime.datetime.now()
>>> print date
2015-03-06 01:25:14.939574
>>> print date.replace(day = 1)
2015-03-01 01:25:14.939574
>>> print date.replace(day = calendar.monthrange(date.year, date.month)[1])
2015-03-31 01:25:14.939574
from datetime import timedelta
(any_day.replace(day=1) + timedelta(days=32)).replace(day=1) - timedelta(days=1)
In Python 3.7 there is the undocumented calendar.monthlen(year, month) function:
>>> calendar.monthlen(2002, 1)
31
>>> calendar.monthlen(2008, 2)
29
>>> calendar.monthlen(2100, 2)
28
It is equivalent to the documented calendar.monthrange(year, month)[1] call.
Another solution would be to do something like this:
from datetime import datetime
def last_day_of_month(year, month):
""" Work out the last day of the month """
last_days = [31, 30, 29, 28, 27]
for i in last_days:
try:
end = datetime(year, month, i)
except ValueError:
continue
else:
return end.date()
return None
And use the function like this:
>>>
>>> last_day_of_month(2008, 2)
datetime.date(2008, 2, 29)
>>> last_day_of_month(2009, 2)
datetime.date(2009, 2, 28)
>>> last_day_of_month(2008, 11)
datetime.date(2008, 11, 30)
>>> last_day_of_month(2008, 12)
datetime.date(2008, 12, 31)
To get the last date of the month we do something like this:
from datetime import date, timedelta
import calendar
last_day = date.today().replace(day=calendar.monthrange(date.today().year, date.today().month)[1])
Now to explain what we are doing here we will break it into two parts:
first is getting the number of days of the current month for which we use monthrange which Blair Conrad has already mentioned his solution:
calendar.monthrange(date.today().year, date.today().month)[1]
second is getting the last date itself which we do with the help of replace e.g
>>> date.today()
datetime.date(2017, 1, 3)
>>> date.today().replace(day=31)
datetime.date(2017, 1, 31)
and when we combine them as mentioned on the top we get a dynamic solution.
if you are willing to use an external library, check out http://crsmithdev.com/arrow/
U can then get the last day of the month with:
import arrow
arrow.utcnow().ceil('month').date()
This returns a date object which you can then do your manipulation.
To me the easier way is using pandas (two lines solution):
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.offsets.MonthEnd(1)
Another way to do it is: Taking the first day of the month, then adding one month and discounting one day:
from datetime import datetime
import pandas as pd
firstday_month = datetime(year, month, 1)
lastday_month = firstday_month + pd.DateOffset(months=1) - pd.DateOffset(days=1)
Use pandas!
def isMonthEnd(date):
return date + pd.offsets.MonthEnd(0) == date
isMonthEnd(datetime(1999, 12, 31))
True
isMonthEnd(pd.Timestamp('1999-12-31'))
True
isMonthEnd(pd.Timestamp(1965, 1, 10))
False
import datetime
now = datetime.datetime.now()
start_month = datetime.datetime(now.year, now.month, 1)
date_on_next_month = start_month + datetime.timedelta(35)
start_next_month = datetime.datetime(date_on_next_month.year, date_on_next_month.month, 1)
last_day_month = start_next_month - datetime.timedelta(1)
Here is another answer. No extra packages required.
datetime.date(year + int(month/12), month%12+1, 1)-datetime.timedelta(days=1)
Get the first day of the next month and subtract a day from it.
That's my way - a function with only two lines:
from dateutil.relativedelta import relativedelta
def last_day_of_month(date):
return date.replace(day=1) + relativedelta(months=1) - relativedelta(days=1)
Example:
from datetime import date
print(last_day_of_month(date.today()))
>> 2021-09-30
The easiest & most reliable way I've found so Far is as:
from datetime import datetime
import calendar
days_in_month = calendar.monthrange(2020, 12)[1]
end_dt = datetime(2020, 12, days_in_month)
you can use relativedelta
https://dateutil.readthedocs.io/en/stable/relativedelta.html
month_end = <your datetime value within the month> + relativedelta(day=31)
that will give you the last day.
This is the simplest solution for me using just the standard datetime library:
import datetime
def get_month_end(dt):
first_of_month = datetime.datetime(dt.year, dt.month, 1)
next_month_date = first_of_month + datetime.timedelta(days=32)
new_dt = datetime.datetime(next_month_date.year, next_month_date.month, 1)
return new_dt - datetime.timedelta(days=1)
Using dateutil.relativedelta
dt + dateutil.relativedelta.relativedelta(months=1, day=1, days=-1)
months=1 and day=1 would shift dt to the first date of next month, then days=-1 would shift the new date to previous date which is exactly the last date of current month.
For me it's the simplest way:
selected_date = date(some_year, some_month, some_day)
if selected_date.month == 12: # December
last_day_selected_month = date(selected_date.year, selected_date.month, 31)
else:
last_day_selected_month = date(selected_date.year, selected_date.month + 1, 1) - timedelta(days=1)
You can calculate the end date yourself. the simple logic is to subtract a day from the start_date of next month. :)
So write a custom method,
import datetime
def end_date_of_a_month(date):
start_date_of_this_month = date.replace(day=1)
month = start_date_of_this_month.month
year = start_date_of_this_month.year
if month == 12:
month = 1
year += 1
else:
month += 1
next_month_start_date = start_date_of_this_month.replace(month=month, year=year)
this_month_end_date = next_month_start_date - datetime.timedelta(days=1)
return this_month_end_date
Calling,
end_date_of_a_month(datetime.datetime.now().date())
It will return the end date of this month. Pass any date to this function. returns you the end date of that month.
The easiest way (without having to import calendar), is to get the first day of the next month, and then subtract a day from it.
import datetime as dt
from dateutil.relativedelta import relativedelta
thisDate = dt.datetime(2017, 11, 17)
last_day_of_the_month = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print last_day_of_the_month
Output:
datetime.datetime(2017, 11, 30, 0, 0)
PS: This code runs faster as compared to the import calendarapproach; see below:
import datetime as dt
import calendar
from dateutil.relativedelta import relativedelta
someDates = [dt.datetime.today() - dt.timedelta(days=x) for x in range(0, 10000)]
start1 = dt.datetime.now()
for thisDate in someDates:
lastDay = dt.datetime(thisDate.year, (thisDate + relativedelta(months=1)).month, 1) - dt.timedelta(days=1)
print ('Time Spent= ', dt.datetime.now() - start1)
start2 = dt.datetime.now()
for thisDate in someDates:
lastDay = dt.datetime(thisDate.year,
thisDate.month,
calendar.monthrange(thisDate.year, thisDate.month)[1])
print ('Time Spent= ', dt.datetime.now() - start2)
OUTPUT:
Time Spent= 0:00:00.097814
Time Spent= 0:00:00.109791
This code assumes that you want the date of the last day of the month (i.e., not just the DD part, but the entire YYYYMMDD date)
The simplest way is to use datetime and some date math, e.g. subtract a day from the first day of the next month:
import datetime
def last_day_of_month(d: datetime.date) -> datetime.date:
return (
datetime.date(d.year + d.month//12, d.month % 12 + 1, 1) -
datetime.timedelta(days=1)
)
Alternatively, you could use calendar.monthrange() to get the number of days in a month (taking leap years into account) and update the date accordingly:
import calendar, datetime
def last_day_of_month(d: datetime.date) -> datetime.date:
return d.replace(day=calendar.monthrange(d.year, d.month)[1])
A quick benchmark shows that the first version is noticeably faster:
In [14]: today = datetime.date.today()
In [15]: %timeit last_day_of_month_dt(today)
918 ns ± 3.54 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [16]: %timeit last_day_of_month_calendar(today)
1.4 µs ± 17.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
This does not address the main question, but one nice trick to get the last weekday in a month is to use calendar.monthcalendar, which returns a matrix of dates, organized with Monday as the first column through Sunday as the last.
# Some random date.
some_date = datetime.date(2012, 5, 23)
# Get last weekday
last_weekday = np.asarray(calendar.monthcalendar(some_date.year, some_date.month))[:,0:-2].ravel().max()
print last_weekday
31
The whole [0:-2] thing is to shave off the weekend columns and throw them out. Dates that fall outside of the month are indicated by 0, so the max effectively ignores them.
The use of numpy.ravel is not strictly necessary, but I hate relying on the mere convention that numpy.ndarray.max will flatten the array if not told which axis to calculate over.
How about more simply:
import datetime
now = datetime.datetime.now()
datetime.date(now.year, 1 if now.month==12 else now.month+1, 1) - datetime.timedelta(days=1)
Here is a long (easy to understand) version but takes care of leap years.
def last_day_month(year, month):
leap_year_flag = 0
end_dates = {
1: 31,
2: 28,
3: 31,
4: 30,
5: 31,
6: 30,
7: 31,
8: 31,
9: 30,
10: 31,
11: 30,
12: 31
}
# Checking for regular leap year
if year % 4 == 0:
leap_year_flag = 1
else:
leap_year_flag = 0
# Checking for century leap year
if year % 100 == 0:
if year % 400 == 0:
leap_year_flag = 1
else:
leap_year_flag = 0
else:
pass
# return end date of the year-month
if leap_year_flag == 1 and month == 2:
return 29
elif leap_year_flag == 1 and month != 2:
return end_dates[month]
else:
return end_dates[month]
import calendar
from time import gmtime, strftime
calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
Output:
31
This will print the last day of whatever the current month is. In this example it was 15th May, 2016. So your output may be different, however the output will be as many days that the current month is. Great if you want to check the last day of the month by running a daily cron job.
So:
import calendar
from time import gmtime, strftime
lastDay = calendar.monthrange(int(strftime("%Y", gmtime())), int(strftime("%m", gmtime())))[1]
today = strftime("%d", gmtime())
lastDay == today
Output:
False
Unless it IS the last day of the month.
I prefer this way
import datetime
import calendar
date=datetime.datetime.now()
month_end_date=datetime.datetime(date.year,date.month,1) + datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1] - 1)