What's the simplest way to subtract a month from a date in Python?

前端 未结 21 1764
[愿得一人]
[愿得一人] 2020-12-02 09:12

If only timedelta had a month argument in it\'s constructor. So what\'s the simplest way to do this?

EDIT: I wasn\'t thinking too hard about this as was poin

相关标签:
21条回答
  • 2020-12-02 09:33

    You could do it in two lines like this:

    now = datetime.now()
    last_month = datetime(now.year, now.month - 1, now.day)
    

    remember the imports

    from datetime import datetime
    
    0 讨论(0)
  • 2020-12-02 09:34

    A vectorized, pandas solution is very simple:

    df['date'] - pd.DateOffset(months=1)

    0 讨论(0)
  • 2020-12-02 09:36

    Try this:

    def monthdelta(date, delta):
        m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
        if not m: m = 12
        d = min(date.day, [31,
            29 if y%4==0 and (not y%100==0 or y%400 == 0) else 28,
            31,30,31,30,31,31,30,31,30,31][m-1])
        return date.replace(day=d,month=m, year=y)
    
    >>> for m in range(-12, 12):
        print(monthdelta(datetime.now(), m))
    
        
    2009-08-06 16:12:27.823000
    2009-09-06 16:12:27.855000
    2009-10-06 16:12:27.870000
    2009-11-06 16:12:27.870000
    2009-12-06 16:12:27.870000
    2010-01-06 16:12:27.870000
    2010-02-06 16:12:27.870000
    2010-03-06 16:12:27.886000
    2010-04-06 16:12:27.886000
    2010-05-06 16:12:27.886000
    2010-06-06 16:12:27.886000
    2010-07-06 16:12:27.886000
    2010-08-06 16:12:27.901000
    2010-09-06 16:12:27.901000
    2010-10-06 16:12:27.901000
    2010-11-06 16:12:27.901000
    2010-12-06 16:12:27.901000
    2011-01-06 16:12:27.917000
    2011-02-06 16:12:27.917000
    2011-03-06 16:12:27.917000
    2011-04-06 16:12:27.917000
    2011-05-06 16:12:27.917000
    2011-06-06 16:12:27.933000
    2011-07-06 16:12:27.933000
    >>> monthdelta(datetime(2010,3,30), -1)
    datetime.datetime(2010, 2, 28, 0, 0)
    >>> monthdelta(datetime(2008,3,30), -1)
    datetime.datetime(2008, 2, 29, 0, 0)
    

    Edit Corrected to handle the day as well.

    Edit See also the answer from puzzlement which points out a simpler calculation for d:

    d = min(date.day, calendar.monthrange(y, m)[1])
    
    0 讨论(0)
  • 2020-12-02 09:36

    Given a (year,month) tuple, where month goes from 1-12, try this:

    >>> from datetime import datetime
    >>> today = datetime.today()
    >>> today
    datetime.datetime(2010, 8, 6, 10, 15, 21, 310000)
    >>> thismonth = today.year, today.month
    >>> thismonth
    (2010, 8)
    >>> lastmonth = lambda (yr,mo): [(y,m+1) for y,m in (divmod((yr*12+mo-2), 12),)][0]
    >>> lastmonth(thismonth)
    (2010, 7)
    >>> lastmonth( (2010,1) )
    (2009, 12)
    

    Assumes there are 12 months in every year.

    0 讨论(0)
  • 2020-12-02 09:37

    I think the simple way is to use DateOffset from Pandas like so:

    import pandas as pd
    date_1 = pd.to_datetime("2013-03-31", format="%Y-%m-%d") - pd.DateOffset(months=1)
    

    The result will be a datetime object

    0 讨论(0)
  • 2020-12-02 09:38

    I Used the following code to go back n Months from a specific Date:

    your_date =  datetime.strptime(input_date, "%Y-%m-%d")  #to convert date(2016-01-01) to timestamp
    start_date=your_date    #start from current date
    
    #Calculate Month
    for i in range(0,n):    #n = number of months you need to go back
        start_date=start_date.replace(day=1)    #1st day of current month
        start_date=start_date-timedelta(days=1) #last day of previous month
    
    #Calculate Day
    if(start_date.day>your_date.day):   
        start_date=start_date.replace(day=your_date.day)            
    
    print start_date
    

    For eg: input date = 28/12/2015 Calculate 6 months previous date.

    I) CALCULATE MONTH: This step will give you the start_date as 30/06/2015.
    Note that after the calculate month step you will get the last day of the required month.

    II)CALCULATE DAY: Condition if(start_date.day>your_date.day) checks whether the day from input_date is present in the required month. This handles condition where input date is 31(or 30) and the required month has less than 31(or 30 in case of feb) days. It handles leap year case as well(For Feb). After this step you will get result as 28/06/2015

    If this condition is not satisfied, the start_date remains the last date of the previous month. So if you give 31/12/2015 as input date and want 6 months previous date, it will give you 30/06/2015

    0 讨论(0)
提交回复
热议问题