philippe
philippe

Reputation: 3179

python date of the previous month

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!

Upvotes: 238

Views: 401024

Answers (19)

bgporter
bgporter

Reputation: 36464

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)
last_month = first - datetime.timedelta(days=1)
print(last_month.strftime("%Y%m"))

201202 is printed.

Upvotes: 509

Adx
Adx

Reputation: 147

It's more easier to use the timedelta module from datetime.

from datetime import datetime, timedelta
now = datetime.now()
lastmonth_date = now - timedelta(days=now.day)

Now, to get last month's number you can use:

lastmonth = lastmonth_date.strftime("%m")

To get the year,

lastmonth_year = lastmonth_date.strftime("%Y")

Upvotes: -1

SAHIL BHANGE
SAHIL BHANGE

Reputation: 741


from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta

#Months(0-12) (1 for Previous month)

#last day of (n) previous month (n=months)
day = datetime(2023, 1, 13)
n = 1
lastDayMonth = ((day - relativedelta(months=n) + relativedelta(day=31)).date());

#First day of previous month (n=months=1)
firstDayMonth = ((day - relativedelta(months=n) + relativedelta(day=1)).date());

print("Last Day of Month - "+ str(lastDayMonth))
print("First Day of Month - "+ str(firstDayMonth))

#Last business day (Friday) of prev (n) month if last day on weekend
lastBusDay = (lastDayMonth - timedelta(max(1,(lastDayMonth.weekday() + 6) % 7 - 3))) if lastDayMonth.weekday() in (5,6) else lastDayMonth

print("Last Business Day of Month - " + str(lastBusinessDay))

print()

Upvotes: 0

user856387
user856387

Reputation: 91

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

Upvotes: 2

Yan Gong
Yan Gong

Reputation: 31

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

Upvotes: 3

Elton da Mata
Elton da Mata

Reputation: 308

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

Upvotes: -2

Ali Naderi
Ali Naderi

Reputation: 403

You can do it as below:

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

Upvotes: -1

DSC
DSC

Reputation: 403

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)

Upvotes: 1

Gil Baggio
Gil Baggio

Reputation: 13963

Simple, one liner:

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

Upvotes: 13

wesinat0r
wesinat0r

Reputation: 300

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

Upvotes: 0

Ehvince
Ehvince

Reputation: 18375

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

Upvotes: 6

Robin Carlo Catacutan
Robin Carlo Catacutan

Reputation: 13679

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

Upvotes: 32

Dave Butler
Dave Butler

Reputation: 1823

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

Upvotes: 126

Mahfuz
Mahfuz

Reputation: 1345

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

Upvotes: 10

steve
steve

Reputation: 41

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

Upvotes: 3

Thane Plummer
Thane Plummer

Reputation: 10208

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

Upvotes: 1

Tiberiu Ichim
Tiberiu Ichim

Reputation: 671

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

Upvotes: 1

Ivan Pirog
Ivan Pirog

Reputation: 3168

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

Upvotes: 60

paragbaxi
paragbaxi

Reputation: 4223

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

Upvotes: 9

Related Questions