पायथन में एक तारीख से एक महीने को घटाने का सबसे सरल तरीका क्या है?


99

यदि केवल टाइमडेल्टा में एक महीने का तर्क था, तो यह निर्माणकर्ता है। तो ऐसा करने का सबसे सरल तरीका क्या है?

संपादित करें: मैं इस बारे में बहुत मुश्किल नहीं सोच रहा था क्योंकि नीचे बताया गया था। वास्तव में जो मैं चाहता था वह पिछले महीने में किसी भी दिन था क्योंकि आखिरकार मैं वर्ष और महीने को हथियाने जा रहा हूं। एक डेटाइम ऑब्जेक्ट दिया गया, तो पिछले महीने में आने वाली किसी भी डेटाइम ऑब्जेक्ट को वापस करने का सबसे सरल तरीका क्या है ?

जवाबों:


62

इसे इस्तेमाल करे:

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

दिन को संभालने के लिए ठीक किया गया संपादित करें ।

संपादित करें पहेली के उत्तर को भी देखें जो इसके लिए एक सरल गणना बताता है d:

d = min(date.day, calendar.monthrange(y, m)[1])

अगर मेरे पास यह सही ((date.month+delta-1) % 12)+1काम है और इसका मतलब if not m: m = 12निकाला जा सकता है
— चार्ल्स एल।

@ डान-क्लेसन आप विस्तृत कर सकते हैं?
— जीन फ़्राँस्वा Fabre

@ जीन-फ्रांस्वा फाबरे पहले वाला सरल नहीं है। इसके अलावा, कोई भी इसे आसानी से डेटाइम और टाइमडेल्टा के साथ कर सकता है।
— दान-क्लैप्सन

हां, ओपी द्वारा संपादित किए जाने के बाद यह स्पष्ट हो जाता है कि वे जो चाहते हैं, dt - timedelta(days=dt.day)जैसा कि मूलरूप से किया जा सकता है, वैसे ही यह लग रहा था कि वे महीनों की मनमानी संख्या को घटाना चाहते हैं और यह थोड़ा कठिन है।
— डंकन

183

आप तीसरे पक्ष के dateutilमॉड्यूल ( यहां PyPI प्रविष्टि ) का उपयोग कर सकते हैं ।

import datetime
import dateutil.relativedelta

d = datetime.datetime.strptime("2013-03-31", "%Y-%m-%d")
d2 = d - dateutil.relativedelta.relativedelta(months=1)
print d2

उत्पादन:

2013-02-28 00:00:00

मैं परम से monthऔर monthsडेटुतिल में उलझन में हूं। परम के साथ घटाव monthकाम नहीं करता है, लेकिन monthsकाम करता है In [23]: created_datetime__lt - relativedelta(months=1) Out[23]: datetime.datetime(2016, 11, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>) In [24]: created_datetime__lt - relativedelta(month=1) Out[24]: datetime.datetime(2016, 1, 29, 0, 0, tzinfo=<StaticTzInfo 'Etc/GMT-8'>)
— सिमिन जी

1
@SiminJie: मुझे लगता है कि उपयोग करने monthsसे 1 महीने का फर्क पड़ेगा। monthइनपुट के महीने की परवाह किए बिना, महीने को 1 पर सेट करना होगा (जैसे जनवरी)।
— फ्रैंक मौलानेर

70

मूल सवाल "पिछले महीने में किसी भी डेटाटाइम ऑब्जेक्ट" के संपादन के बाद, आप इसे महीने के पहले दिन से 1 दिन घटाकर बहुत आसानी से कर सकते हैं।

from datetime import datetime, timedelta

def a_day_in_previous_month(dt):
   return dt.replace(day=1) - timedelta(days=1)

4
आप इस्तेमाल कर सकते हैंdt.replace(day=1) - timedelta(1)
— JFS

3
याdt - timedelta(days=dt.day)
— SergiyKolesnikov

23

डंकन के उत्तर पर एक भिन्नता (मेरे पास टिप्पणी करने के लिए पर्याप्त प्रतिष्ठा नहीं है), जो कैलेंडर के महीने के अंतिम दिन की गणना को सरल बनाने के लिए Calendar.monthrange का उपयोग करता है:

import calendar
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, calendar.monthrange(y, m)[1])
    return date.replace(day=d,month=m, year=y)

पाइथन में माह के अंतिम दिन से व्यवस्था पर जानकारी


22

एक सदिश, पंडों का समाधान बहुत सरल है:

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


धन्यवाद! इसने मुझे अपनी तिथियों के सेट से / महीने में / आसानी से जोड़ने में मदद की!
— माटुस दा सिल्वा टेइसीरा

यह अच्छा है अगर आप उपयोग कर सकते हैं pandas। धन्यवाद!
— आइगर्कफ

17

यदि केवल टाइमडेल्टा में एक महीने का तर्क था, तो यह निर्माणकर्ता है। तो ऐसा करने का सबसे सरल तरीका क्या है?

जब आप 30 मार्च से एक महीना घटाते हैं, तो आप क्या परिणाम चाहते हैं? महीनों को जोड़ने या घटाने में यही समस्या है: महीनों की लंबाई अलग-अलग होती है! कुछ आवेदन में एक अपवाद ऐसे मामलों में उचित दूसरों में है, "पिछले महीने के अंतिम दिन" उपयोग करने के लिए ठीक है (लेकिन है कि वास्तव में पागल गणित, जब फिर एक महीने घटाकर एक महीने जोड़ने है नहीं समग्र नो-आपरेशन!) दूसरों में, फिर भी आप तारीख के अलावा इस तथ्य के बारे में कुछ संकेत रखना चाहते हैं, उदाहरण के लिए, "मैं 28 फरवरी को कह रहा हूं, लेकिन मैं वास्तव में 30 फरवरी चाहता हूं यदि यह अस्तित्व में है", ताकि किसी अन्य महीने को जोड़ना या घटाना वह चीजें फिर से सेट कर सकता है (और बाद के स्पष्ट रूप से एक कस्टम वर्ग को डेटा प्लस एस / चीज रखने की आवश्यकता होती है)।

कोई भी वास्तविक समाधान नहीं हो सकता है जो सभी अनुप्रयोगों के लिए सहन करने योग्य हो, और आपने हमें यह नहीं बताया है कि इस मनहूस ऑपरेशन के शब्दार्थ के लिए आपके विशिष्ट ऐप की क्या आवश्यकता है, इसलिए बहुत अधिक सहायता नहीं है जो हम यहां प्रदान कर सकते हैं।


आप बिल्कुल सही कह रहे है। क्या सिर्फ समयसीमा का मजाक उड़ाया गया था, उसके लिए एक तर्क था। मुझे आश्चर्य है कि अगर एक ही तर्क घंटों या मिनटों के लिए तर्क नहीं होने के लिए लागू होता है। तकनीकी रूप से एक दिन ठीक 24 घंटे नहीं है।
— 15 फरवरी को Bialecki

PHP 28 फरवरी को 2 दिन जोड़कर संभालती है , और यह 2 मार्च को जाती है। इसके लिए कन्वेंशन हैं, मैं उन्हें वास्तविक त्वरित
— खोजता हूं

यह और भी दिलचस्प हो जाता है अगर आप मुद्रा विनिमय के लिए तारीखों की गणना कर रहे हैं: उदाहरण के लिए आपको भविष्य में 3 या 6 महीने पहले एक तिथि कहने की आवश्यकता हो सकती है, लेकिन यह दोनों देशों में कार्य दिवस होना चाहिए (शुक्रवार को मॉस्लेम देशों में नहीं) और किसी भी देश में बैंक अवकाश नहीं है।
— डंकन

@ बियाल्की: datetimeमॉड्यूल मानता है कि एक दिन ठीक 24 घंटे (कोई छलांग सेकंड) नहीं है
— jfs

8

मुझे लगता है कि पंडों से डेटऑफसेट का उपयोग करने का सरल तरीका है:

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

परिणाम एक डेटाइम ऑब्जेक्ट होगा


2
यह सबसे सहज समाधान है
— Kots

5

यदि आप चाहते हैं कि अंतिम महीने में कोई भी दिन हो, तो आप जो सबसे सरल काम कर सकते हैं, वह वर्तमान तिथि से दिनों की संख्या को घटा देना है, जो आपको पिछले महीने के अंतिम दिन देगा।

उदाहरण के लिए, किसी भी तारीख से शुरू:

>>> import datetime                                                                                                                                                                 
>>> today = datetime.date.today()                                                                                                                                                   
>>> today
datetime.date(2016, 5, 24)

वर्तमान तिथि के दिनों को घटाकर हम प्राप्त करते हैं:

>>> last_day_previous_month = today - datetime.timedelta(days=today.day)
>>> last_day_previous_month
datetime.date(2016, 4, 30)

यह पिछले महीने में किसी भी दिन की आपकी सरल आवश्यकता के लिए पर्याप्त है।

लेकिन अब जब आपके पास यह है, तो आप महीने में किसी भी दिन भी प्राप्त कर सकते हैं, उसी दिन से, जिस दिन आपने शुरुआत की थी (यानी कम या ज्यादा एक महीने को घटाते हुए):

>>> same_day_last_month = last_day_previous_month.replace(day=today.day)
>>> same_day_last_month
datetime.date(2016, 4, 24)

बेशक, आपको 30 दिन के महीने में 31 तारीख या फरवरी से गायब होने वाले दिनों से सावधान रहने की जरूरत है (और लीप वर्ष का ध्यान रखें), लेकिन ऐसा करना भी आसान है:

>>> a_date = datetime.date(2016, 3, 31)                                                                                                                                             
>>> last_day_previous_month = a_date - datetime.timedelta(days=a_date.day)
>>> a_date_minus_month = (
...     last_day_previous_month.replace(day=a_date.day)
...     if a_date.day < last_day_previous_month.day
...     else last_day_previous_month
... )
>>> a_date_minus_month
datetime.date(2016, 2, 29)

1

मैं इसका उपयोग सरकारी वित्तीय वर्षों के लिए करता हूं जहां Q4 1 अक्टूबर से शुरू होता है। नोट मैं तिथि को क्वार्टर में परिवर्तित करता हूं और इसे पूर्ववत भी करता हूं।

import pandas as pd

df['Date'] = '1/1/2020'
df['Date'] = pd.to_datetime(df['Date'])              #returns 2020-01-01
df['NewDate'] = df.Date - pd.DateOffset(months=3)    #returns 2019-10-01 <---- answer

# For fun, change it to FY Quarter '2019Q4'
df['NewDate'] = df['NewDate'].dt.year.astype(str) + 'Q' + df['NewDate'].dt.quarter.astype(str)

# Convert '2019Q4' back to 2019-10-01
df['NewDate'] = pd.to_datetime(df.NewDate)

0

यहाँ कुछ कोड ऐसा करने के लिए है। खुद को आजमाया नहीं ...

def add_one_month(t):
    """Return a `datetime.date` or `datetime.datetime` (as given) that is
    one month earlier.

    Note that the resultant day of the month might change if the following
    month has fewer days:

        >>> add_one_month(datetime.date(2010, 1, 31))
        datetime.date(2010, 2, 28)
    """
    import datetime
    one_day = datetime.timedelta(days=1)
    one_month_later = t + one_day
    while one_month_later.month == t.month:  # advance to start of next month
        one_month_later += one_day
    target_month = one_month_later.month
    while one_month_later.day < t.day:  # advance to appropriate day
        one_month_later += one_day
        if one_month_later.month != target_month:  # gone too far
            one_month_later -= one_day
            break
    return one_month_later

def subtract_one_month(t):
    """Return a `datetime.date` or `datetime.datetime` (as given) that is
    one month later.

    Note that the resultant day of the month might change if the following
    month has fewer days:

        >>> subtract_one_month(datetime.date(2010, 3, 31))
        datetime.date(2010, 2, 28)
    """
    import datetime
    one_day = datetime.timedelta(days=1)
    one_month_earlier = t - one_day
    while one_month_earlier.month == t.month or one_month_earlier.day > t.day:
        one_month_earlier -= one_day
    return one_month_earlier

0

यह देखते हुए (वर्ष, माह) टपल, जहां माह 1-12 से जाता है, यह प्रयास करें:

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

मान लें कि हर साल 12 महीने होते हैं।


0
def month_sub(year, month, sub_month):
    result_month = 0
    result_year = 0
    if month > (sub_month % 12):
        result_month = month - (sub_month % 12)
        result_year = year - (sub_month / 12)
    else:
        result_month = 12 - (sub_month % 12) + month
        result_year = year - (sub_month / 12 + 1)
    return (result_year, result_month)

>>> month_sub(2015, 7, 1)    
(2015, 6)
>>> month_sub(2015, 7, -1)
(2015, 8)
>>> month_sub(2015, 7, 13)
(2014, 6)
>>> month_sub(2015, 7, -14)
(2016, 9)

0

मैंने किसी विशिष्ट दिनांक से n महीने वापस जाने के लिए निम्न कोड का उपयोग किया:

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

उदाहरण के लिए: इनपुट दिनांक = 28/12/2015 6 महीने पिछली तारीख की गणना करें।

I) CALCULATE MONTH: यह चरण आपको 30/06/2015 के रूप में start_date देगा।
ध्यान दें कि गणना महीने के चरण के बाद आपको आवश्यक महीने का अंतिम दिन मिलेगा।

II) CALCULATE DAY: शर्त यदि (start_date.day> your_date.day) यह जांचती है कि इनपुट_डेट से दिन आवश्यक माह में मौजूद है या नहीं। यह ऐसी स्थिति को संभालता है जहां इनपुट की तारीख 31 (या 30) है और आवश्यक महीने में 31 (या फेब के मामले में 30) से कम है। यह लीप वर्ष के मामले को भी संभालता है (For Feb)। इस कदम के बाद आपको परिणाम 28/06/2015 के रूप में मिलेगा

यदि यह स्थिति संतुष्ट नहीं है, तो start_date पिछले महीने की अंतिम तारीख बनी हुई है। इसलिए यदि आप 31/12/2015 को इनपुट तिथि के रूप में देते हैं और 6 महीने पहले की तारीख चाहते हैं, तो यह आपको 30/06/2015 देगा


0

आप एक्स महीने के पहले / बाद की तारीख पाने के लिए दिए गए फ़ंक्शन का उपयोग कर सकते हैं।

डेटाइम आयात तिथि से

अगले अगले महीने (दिया_ महीना),:
    yyyy = int (((दिया_अध्याय * १२ + दिया_दाते समय) + महीना) / १२)
    mm = int (((दिया_डेट। * * 12 + दिया_डेटा) + महीना)% 12)

    यदि मिमी == 0:
        य्येय - = १
        मिमी = 12

    दिए गए रिटर्न_टेट .replace (वर्ष = yyyy, महीना = मिमी)


अगर __name__ == "__main__":
    आज = date.today ()
    प्रिंट (आज)

    [-12, -1, 0, 1, 2, 12, 20] में मिमी के लिए:
        अगला_डेट = अगला_ महीना (आज, मिमी)
        प्रिंट (next_date)

0

मुझे लगता है कि यह उत्तर काफी पठनीय है:

def month_delta(dt, delta):
    year_delta, month = divmod(dt.month + delta, 12)

    if month == 0:
        # convert a 0 to december
        month = 12
        if delta < 0:
            # if moving backwards, then it's december of last year
            year_delta -= 1

    year = dt.year + year_delta

    return dt.replace(month=month, year=year)

for delta in range(-20, 21):
    print(delta, "->", month_delta(datetime(2011, 1, 1), delta))

-20 -> 2009-05-01 00:00:00
-19 -> 2009-06-01 00:00:00
-18 -> 2009-07-01 00:00:00
-17 -> 2009-08-01 00:00:00
-16 -> 2009-09-01 00:00:00
-15 -> 2009-10-01 00:00:00
-14 -> 2009-11-01 00:00:00
-13 -> 2009-12-01 00:00:00
-12 -> 2010-01-01 00:00:00
-11 -> 2010-02-01 00:00:00
-10 -> 2010-03-01 00:00:00
-9 -> 2010-04-01 00:00:00
-8 -> 2010-05-01 00:00:00
-7 -> 2010-06-01 00:00:00
-6 -> 2010-07-01 00:00:00
-5 -> 2010-08-01 00:00:00
-4 -> 2010-09-01 00:00:00
-3 -> 2010-10-01 00:00:00
-2 -> 2010-11-01 00:00:00
-1 -> 2010-12-01 00:00:00
0 -> 2011-01-01 00:00:00
1 -> 2011-02-01 00:00:00
2 -> 2011-03-01 00:00:00
3 -> 2011-04-01 00:00:00
4 -> 2011-05-01 00:00:00
5 -> 2011-06-01 00:00:00
6 -> 2011-07-01 00:00:00
7 -> 2011-08-01 00:00:00
8 -> 2011-09-01 00:00:00
9 -> 2011-10-01 00:00:00
10 -> 2011-11-01 00:00:00
11 -> 2012-12-01 00:00:00
12 -> 2012-01-01 00:00:00
13 -> 2012-02-01 00:00:00
14 -> 2012-03-01 00:00:00
15 -> 2012-04-01 00:00:00
16 -> 2012-05-01 00:00:00
17 -> 2012-06-01 00:00:00
18 -> 2012-07-01 00:00:00
19 -> 2012-08-01 00:00:00
20 -> 2012-09-01 00:00:00

0

एक लाइन ?

previous_month_date = (current_date - datetime.timedelta(days=current_date.day+1)).replace(day=current_date.day)


0

सरल तरीका है कि मैंने अभी-अभी कोशिश की है

from datetime import datetime
from django.utils import timezone





current = timezone.now()
if current.month == 1:
     month = 12
else:
     month = current.month - 1
current = datetime(current.year, month, current.day)

0

कुछ समय पहले मैं निम्नलिखित एल्गोरिथ्म में आया था जो dateया तो एक महीने में वेतन वृद्धि और गिरावट के लिए बहुत अच्छी तरह से काम करता है datetime।

गुफा : यह विफल हो जाएगा अगर dayनए महीने में उपलब्ध नहीं है। मैं इसे डेट ऑब्जेक्ट्स पर उपयोग करता हूं जहां day == 1हमेशा।

अजगर 3.x:

def increment_month(d, add=1):
    return date(d.year+(d.month+add-1)//12, (d.month+add-1) % 12+1, 1)

अजगर के लिए 2.7 पूर्णांक विभाजन के निहित होने के बाद //12से ही इसे बदल दें /12।

मैंने हाल ही में एक डिफॉल्ट फाइल में इसका इस्तेमाल किया था जब एक स्क्रिप्ट को इन उपयोगी ग्लोबल्स को प्राप्त करना शुरू हुआ था:

MONTH_THIS = datetime.date.today()
MONTH_THIS = datetime.date(MONTH_THIS.year, MONTH_THIS.month, 1)

MONTH_1AGO = datetime.date(MONTH_THIS.year+(MONTH_THIS.month-2)//12,
                           (MONTH_THIS.month-2) % 12+1, 1)

MONTH_2AGO = datetime.date(MONTH_THIS.year+(MONTH_THIS.month-3)//12,
                           (MONTH_THIS.month-3) % 12+1, 1)

-2
import datetime
date_str = '08/01/2018'
format_str = '%d/%m/%Y'
datetime_obj = datetime.datetime.strptime(date_str, format_str)   
datetime_obj.replace(month=datetime_obj.month-1)

सरल समाधान, विशेष पुस्तकालयों के लिए कोई ज़रूरत नहीं है।


2
जब 31 मार्च जैसी तारीख हो तो काम नहीं करेंगे।
— फायरस्टॉक

1
या 1 जनवरी की तरह
— LeandroHumb

-3

आप इसे इस तरह से दो लाइनों में कर सकते हैं:

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

आयात याद है

from datetime import datetime

1
क्या हुआ अगर यह जन है?
— सर्गेई
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.