python date of the previous month

PythonDateTime

Python Problem Overview


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!

Python Solutions


Solution 1 - Python

datetime and the datetime.timedelta classes are your friend.

  1. find today.
  2. use that to find the first day of this month.
  3. use timedelta to backup a single day, to the last day of the previous month.
  4. 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.

Solution 2 - Python

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

Solution 3 - Python

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

Solution 4 - Python

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

Solution 5 - Python

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'))

Solution 6 - Python

Simple, one liner:

import datetime as dt
previous_month = (dt.date.today().replace(day=1) - dt.timedelta(days=1)).month

Solution 7 - Python

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

Solution 8 - Python

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

Solution 9 - Python

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))

Solution 10 - Python

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

Solution 11 - Python

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')

Solution 12 - Python

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)

Solution 13 - Python

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

Solution 14 - Python

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")

Solution 15 - Python

You can do it as below:

from datetime import datetime, timedelta    
last_month = (datetime.now() - timedelta(days=32)).strftime("%Y%m")

Solution 16 - Python

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

Solution 17 - Python

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionphilippeView Question on Stackoverflow
Solution 1 - PythonbgporterView Answer on Stackoverflow
Solution 2 - PythonDave ButlerView Answer on Stackoverflow
Solution 3 - PythonIvan PirogView Answer on Stackoverflow
Solution 4 - PythonRobin Carlo CatacutanView Answer on Stackoverflow
Solution 5 - PythonparagbaxiView Answer on Stackoverflow
Solution 6 - PythonGil BaggioView Answer on Stackoverflow
Solution 7 - PythonMahfuzView Answer on Stackoverflow
Solution 8 - PythonEhvinceView Answer on Stackoverflow
Solution 9 - PythonsteveView Answer on Stackoverflow
Solution 10 - PythonTiberiu IchimView Answer on Stackoverflow
Solution 11 - Pythonwesinat0rView Answer on Stackoverflow
Solution 12 - PythonDRSView Answer on Stackoverflow
Solution 13 - PythonThane PlummerView Answer on Stackoverflow
Solution 14 - PythonElton da MataView Answer on Stackoverflow
Solution 15 - PythonAli NaderiView Answer on Stackoverflow
Solution 16 - PythonYan GongView Answer on Stackoverflow
Solution 17 - Pythonuser856387View Answer on Stackoverflow