I am trying to get the date of the previous month with python.
Here is what i’ve tried:
str( time.strftime('%Y') ) + str( int(time.strftime('%m'))-1 )
However, this way is bad for 2 reasons: First it returns 20122 for the February of 2012 (instead of 201202) and secondly it will return 0 instead of 12 on January.
I have solved this trouble in bash with
echo $(date -d"3 month ago" "+%G%m%d")
I think that if bash has a built-in way for this purpose, then python, much more equipped, should provide something better than forcing writing one’s own script to achieve this goal. Of course i could do something like:
if int(time.strftime('%m')) == 1:
return '12'
else:
if int(time.strftime('%m')) < 10:
return '0'+str(time.strftime('%m')-1)
else:
return str(time.strftime('%m') -1)
I have not tested this code and i don’t want to use it anyway (unless I can’t find any other way:/)
Thanks for your help!
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
datetime and the datetime.timedelta classes are your friend.
- find today.
- use that to find the first day of this month.
- use timedelta to backup a single day, to the last day of the previous month.
- print the YYYYMM string you’re looking for.
Like this:
import datetime
today = datetime.date.today()
first = today.replace(day=1)
lastMonth = first - datetime.timedelta(days=1)
print(lastMonth.strftime("%Y%m"))
201202 is printed.
Method 2
You should use dateutil.
With that, you can use relativedelta, it’s an improved version of timedelta.
>>> import datetime >>> import dateutil.relativedelta >>> now = datetime.datetime.now() >>> print now 2012-03-15 12:33:04.281248 >>> print now + dateutil.relativedelta.relativedelta(months=-1) 2012-02-15 12:33:04.281248
Method 3
from datetime import date, timedelta first_day_of_current_month = date.today().replace(day=1) last_day_of_previous_month = first_day_of_current_month - timedelta(days=1) print "Previous month:", last_day_of_previous_month.month
Or:
from datetime import date, timedelta prev = date.today().replace(day=1) - timedelta(days=1) print prev.month
Method 4
For someone who got here and looking to get both the first and last day of the previous month:
from datetime import date, timedelta
last_day_of_prev_month = date.today().replace(day=1) - timedelta(days=1)
start_day_of_prev_month = date.today().replace(day=1) - timedelta(days=last_day_of_prev_month.day)
# For printing results
print("First day of prev month:", start_day_of_prev_month)
print("Last day of prev month:", last_day_of_prev_month)
Output:
First day of prev month: 2019-02-01 Last day of prev month: 2019-02-28
Method 5
Building on bgporter’s answer.
def prev_month_range(when = None):
"""Return (previous month's start date, previous month's end date)."""
if not when:
# Default to today.
when = datetime.datetime.today()
# Find previous month: https://stackoverflow.com/a/9725093/564514
# Find today.
first = datetime.date(day=1, month=when.month, year=when.year)
# Use that to find the first day of this month.
prev_month_end = first - datetime.timedelta(days=1)
prev_month_start = datetime.date(day=1, month= prev_month_end.month, year= prev_month_end.year)
# Return previous month's start and end dates in YY-MM-DD format.
return (prev_month_start.strftime('%Y-%m-%d'), prev_month_end.strftime('%Y-%m-%d'))
Method 6
Simple, one liner:
import datetime as dt previous_month = (dt.date.today().replace(day=1) - dt.timedelta(days=1)).month
Method 7
Its very easy and simple. Do this
from dateutil.relativedelta import relativedelta from datetime import datetime today_date = datetime.today() print "todays date time: %s" %today_date one_month_ago = today_date - relativedelta(months=1) print "one month ago date time: %s" % one_month_ago print "one month ago date: %s" % one_month_ago.date()
Here is the output:
$python2.7 main.py
todays date time: 2016-09-06 02:13:01.937121 one month ago date time: 2016-08-06 02:13:01.937121 one month ago date: 2016-08-06
Method 8
With the Pendulum very complete library, we have the subtract method (and not “subStract”):
import pendulum
today = pendulum.datetime.today() # 2020, january
lastmonth = today.subtract(months=1)
lastmonth.strftime('%Y%m')
# '201912'
We see that it handles jumping years.
The reverse equivalent is add.
https://pendulum.eustace.io/docs/#addition-and-subtraction
Method 9
def prev_month(date=datetime.datetime.today()):
if date.month == 1:
return date.replace(month=12,year=date.year-1)
else:
try:
return date.replace(month=date.month-1)
except ValueError:
return prev_month(date=date.replace(day=date.day-1))
Method 10
Just for fun, a pure math answer using divmod. Pretty inneficient because of the multiplication, could do just as well a simple check on the number of month (if equal to 12, increase year, etc)
year = today.year
month = today.month
nm = list(divmod(year * 12 + month + 1, 12))
if nm[1] == 0:
nm[1] = 12
nm[0] -= 1
pm = list(divmod(year * 12 + month - 1, 12))
if pm[1] == 0:
pm[1] = 12
pm[0] -= 1
next_month = nm
previous_month = pm
Method 11
There is a high level library dateparser that can determine the past date given natural language, and return the corresponding Python datetime object
from dateparser import parse
parse('4 months ago')
Method 12
You might have come here because you’re working with Jython in NiFi. This is how I ended up implementing it. I deviated a little from this answer by Robin Carlo Catacutan because accessing last_day_of_prev_month.day wasn’t possible due to a Jython datatype issue explained here that for some reason seems to exist in NiFi’S Jython but not in vanilla Jython.
from datetime import date, timedelta
import calendar
flowFile = session.get()
if flowFile != None:
first_weekday_in_prev_month, num_days_in_prev_month = calendar.monthrange(date.today().year,date.today().month-1)
last_day_of_prev_month = date.today().replace(day=1) - timedelta(days=1)
first_day_of_prev_month = date.today().replace(day=1) - timedelta(days=num_days_in_prev_month)
last_day_of_prev_month = str(last_day_of_prev_month)
first_day_of_prev_month = str(first_day_of_prev_month)
flowFile = session.putAllAttributes(flowFile, {
"last_day_of_prev_month": last_day_of_prev_month,
"first_day_of_prev_month": first_day_of_prev_month
})
session.transfer(flowFile, REL_SUCCESS)
Method 13
Explicit way:
import datetime result = (datetime.datetime.today().month - 2) % 12 + 1
The problem is how to transfer month [1, 2, 3, …, 12] to [12, 1, 2, …, 11].
Step1: month = month - 1 transfer [1, 2, 3, …, 12] to [0, 1, 2, …, 11].
Step2: month = (month - 1) % 12 transfer [0, 1, 2, …, 11] to [11, 0, 1, …, 10].
Step3: month = month + 1 transfer [11, 0, 1, …, 10] to [12, 1, 2, …, 11].
So, the result is result = (month - 2) % 12 + 1
Method 14
from datetime import datetime, timedelta, time, timezone current_time = datetime.now(timezone.utc) last_day_previous_month = datetime.combine(current_time.replace(day=1), time.max) - timedelta(days=1) first_day_previous_month = datetime.combine(last_day_previous_month, time.min).replace(day=1)
Output:
first_day_previous_month: 2022-02-01 00:00:00 last_day_previous_month: 2022-02-28 23:59:59.999999
Method 15
Building off the comment of @J.F. Sebastian, you can chain the replace() function to go back one “month”. Since a month is not a constant time period, this solution tries to go back to the same date the previous month, which of course does not work for all months. In such a case, this algorithm defaults to the last day of the prior month.
from datetime import datetime, timedelta
d = datetime(2012, 3, 31) # A problem date as an example
# last day of last month
one_month_ago = (d.replace(day=1) - timedelta(days=1))
try:
# try to go back to same day last month
one_month_ago = one_month_ago.replace(day=d.day)
except ValueError:
pass
print("one_month_ago: {0}".format(one_month_ago))
Output:
one_month_ago: 2012-02-29 00:00:00
Method 16
You can do it as below:
from datetime import datetime, timedelta
last_month = (datetime.now() - timedelta(days=32)).strftime("%Y%m")
Method 17
import pandas as pd
lastmonth = int(pd.to_datetime("today").strftime("%Y%m"))-1
print(lastmonth)
202101
from datetime import date, timedelta
YYYYMM = (date.today().replace(day=1)-timedelta(days=1)).strftime("%Y%m")
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0