दो तिथियों के बीच के महीनों को खोजने का सबसे अच्छा तरीका


91

मुझे अजगर में दो तारीखों के बीच के महीनों का सही पता लगाने में सक्षम होने की आवश्यकता है। मेरे पास एक समाधान है जो काम करता है लेकिन यह बहुत अच्छा नहीं है (जैसे कि सुरुचिपूर्ण) या तेज।

dateRange = [datetime.strptime(dateRanges[0], "%Y-%m-%d"), datetime.strptime(dateRanges[1], "%Y-%m-%d")]
months = [] 

tmpTime = dateRange[0]
oneWeek = timedelta(weeks=1)
tmpTime = tmpTime.replace(day=1)
dateRange[0] = tmpTime
dateRange[1] = dateRange[1].replace(day=1)
lastMonth = tmpTime.month
months.append(tmpTime)
while tmpTime < dateRange[1]:
    if lastMonth != 12:
        while tmpTime.month <= lastMonth:
            tmpTime += oneWeek
        tmpTime = tmpTime.replace(day=1)
        months.append(tmpTime)
        lastMonth = tmpTime.month

    else:
        while tmpTime.month >= lastMonth:
            tmpTime += oneWeek
        tmpTime = tmpTime.replace(day=1)
        months.append(tmpTime)
        lastMonth = tmpTime.month

तो बस समझाने के लिए, मैं यहाँ क्या कर रहा हूँ दो तिथियों को ले रहा हूँ और उन्हें आयत प्रारूप से अजगर डेटाइम वस्तुओं में परिवर्तित कर रहा हूँ। फिर मैं आरंभिक डेटटाइम ऑब्जेक्ट में एक हफ़्ते जोड़ने के माध्यम से लूप करता हूं और जांचता हूं कि क्या महीने का संख्यात्मक मूल्य अधिक है (जब तक कि दिसंबर दिसंबर नहीं है, तो यह जांचता है कि तारीख कम है), यदि मूल्य अधिक है तो मैं इसे सूची में जोड़ता हूं जब तक मैं अपनी अंतिम तिथि तक प्राप्त नहीं कर लेता हूँ

यह पूरी तरह से काम करता है यह सिर्फ इसे करने का एक अच्छा तरीका की तरह प्रतीत नहीं होता है ...


क्या आप दो तिथियों के बीच के महीनों की संख्या पूछ रहे हैं, या वास्तविक महीने क्या हैं?
चार्ल्स हूपर

मेरे समाधान में: मैं "सेकंड की संख्या के एक महीने के मूल्य" से वृद्धि नहीं कर रहा हूं। मैं केवल 1 से 2 की संख्या बढ़ा रहा हूं, और फिर 2 से 3 तक बाद में।
६opol:

मैं सिर्फ आपको यह जानना चाहता था कि भले ही आपको मेरा जवाब पसंद नहीं आया हो, क्योंकि इसमें "पाश" था, आपने एक जवाब चुना जिसमें दो लूप हैं। सूची बोध अभी भी लूप हैं।
चार्ल्स हूपर

जवाबों:


0

अपडेट 2018-04-20: ऐसा लगता है कि ओपी @ जोशकुंज यह पता लगाने के लिए कह रहा था कि दो तारीखों के बीच कौन से महीने दो तारीखों के बीच हैं, दो तारीखों के बीच कितने महीने हैं। इसलिए मुझे यकीन नहीं है कि @JohnLaRooy 100 से अधिक बार क्यों उखाड़ा जाता है। @ जोशकुंज ने मूल प्रश्न के तहत टिप्पणी में संकेत दिया कि वह वास्तविक तारीखें [या महीने] चाहता था, इसके बजाय महीनों की कुल संख्या का पता लगाना ।

तो यह दो तिथियों के बीच के लिए सवाल थे, दिखाई दिया 2018-04-11करने के लिए2018-06-01

Apr 2018, May 2018, June 2018 

और क्या यह के बीच है अगर 2014-04-11करने के लिए 2018-06-01? तो जवाब होगा

Apr 2014, May 2014, ..., Dec 2014, Jan 2015, ..., Jan 2018, ..., June 2018

तो इसीलिए मेरे पास कई साल पहले निम्न छद्म कोड था। यह महज दो महीने के अंत बिंदुओं और उनके माध्यम से लूप का उपयोग करने का सुझाव देता है, एक समय में एक महीने तक बढ़ाना। @ जोशकुंज ने उल्लेख किया कि वह "महीने" चाहता था और उसने यह भी उल्लेख किया कि वह "तारीखें" चाहता था, ठीक-ठीक जानने के बिना, सटीक कोड लिखना मुश्किल था, लेकिन विचार एक साधारण लूप का उपयोग करने के लिए अंत बिंदुओं के माध्यम से लूप करना है, और एक महीने में एक महीने की वृद्धि।

जवाब 8 साल पहले 2010 में:

यदि एक सप्ताह से जोड़ दें, तो यह लगभग 4.35 गुना काम को आवश्यकतानुसार करेगा। सिर्फ क्यों नहीं:

1. get start date in array of integer, set it to i: [2008, 3, 12], 
       and change it to [2008, 3, 1]
2. get end date in array: [2010, 10, 26]
3. add the date to your result by parsing i
       increment the month in i
       if month is >= 13, then set it to 1, and increment the year by 1
   until either the year in i is > year in end_date, 
           or (year in i == year in end_date and month in i > month in end_date)

अभी के लिए बस pseduo कोड, परीक्षण नहीं किया है, लेकिन मुझे लगता है कि एक ही लाइन के साथ विचार काम करेगा।


1
ठीक है, मुझे फरवरी जैसी महीनों के साथ कुछ समस्याएं दिखती हैं अगर वृद्धि महीने से होती है। हफ्तों की तुलना में।
जोशकुंज

मैं "सेकंड की संख्या के एक महीने के मूल्य" से नहीं बढ़ रहा हूँ। मैं केवल संख्या बढ़ाने हूँ 1करने के लिए 2, और फिर से 2करने के लिए 3बाद में।

194

कुछ परीक्षण मामलों को परिभाषित करके शुरू करें, फिर आप देखेंगे कि फ़ंक्शन बहुत सरल है और लूप की आवश्यकता नहीं है

from datetime import datetime

def diff_month(d1, d2):
    return (d1.year - d2.year) * 12 + d1.month - d2.month

assert diff_month(datetime(2010,10,1), datetime(2010,9,1)) == 1
assert diff_month(datetime(2010,10,1), datetime(2009,10,1)) == 12
assert diff_month(datetime(2010,10,1), datetime(2009,11,1)) == 11
assert diff_month(datetime(2010,10,1), datetime(2009,8,1)) == 14

आपको अपने प्रश्न में कुछ परीक्षण मामलों को जोड़ना चाहिए, क्योंकि कवर करने के लिए बहुत सारे संभावित कोने के मामले हैं - दो तिथियों के बीच महीनों की संख्या को परिभाषित करने का एक से अधिक तरीका है।


2
यह गलत परिणाम देता है। यह "2015-04-30" और "2015-05-01" के बीच 1 महीने का परिणाम देता है जो वास्तव में सिर्फ 1 दिन है।
राव

21
@Rao। इसलिए मैंने कहा "दो तिथियों के बीच महीनों की संख्या को परिभाषित करने का एक से अधिक तरीका है"। प्रश्न में अभी भी औपचारिक परिभाषा का अभाव है। ऐसा इसलिए भी है क्योंकि मेरा सुझाव है कि परिभाषा के साथ-साथ टेस्टकेस भी उपलब्ध कराए जाने चाहिए।
जॉन ला रोय

2
मैं पेट () substractions चारों ओर जोड़ने के लिए d2 की तुलना में छोटा d1 अनुमति देने के लिए सलाह देते हैं: वापसी पेट (d1.year - d2.year) * 12 + पेट (d1.month - d2.month)
लुकास शुल्ज़

क्या आपको यकीन है, @LukasSchulze? यदि d1 d2 से छोटा है, तो आपको उस संख्या को पहले वाले से कहीं भी घटाना होगा, है ना?
लिलिथ-एलिना

लेकिन मेरे मामले में, यह कोई फर्क नहीं पड़ता कि क्या d1 <= d2 या d2 <= d1 है। आप केवल अंतर में रुचि रखते हैं, कोई फर्क नहीं पड़ता कि दोनों में से कौन सी तारीख छोटी / बड़ी है।
लुकास शुल्ज

40

एक लाइनर दो तारीखों के बीच, महीने के हिसाब से बढ़ाए गए डेटासेट की एक सूची खोजने के लिए।

import datetime
from dateutil.rrule import rrule, MONTHLY

strt_dt = datetime.date(2001,1,1)
end_dt = datetime.date(2005,6,1)

dates = [dt for dt in rrule(MONTHLY, dtstart=strt_dt, until=end_dt)]

यह! यह बहुत सारे फैंसी विशेष स्थितियों के लिए समायोजित करता है, जो कि रूले का उपयोग करने के लिए धन्यवाद। ध्यान दें कि आउटपुट वैल्यू डेटाइम हैं इसलिए आप उन्हें जो कुछ भी दिखा रहे हैं उसे मैच करने के लिए (स्ट्रिंग्स सहित) में कन्वर्ट कर सकते हैं।
ईजेकील क्रुगलिक

यह तब विफल हो जाता है जब उस वर्ष कोई लीप दिवस नहीं होने के कारण strt_dt 2001-1-29 होता है।
CS

2
ओपी ने शुरुआत और समाप्ति तिथियों के बीच महीनों की एक सूची मांगी। फरवरी मेरे उदाहरण पर आपकी विधि का उपयोग करने से चूक गया। बेशक, आपका समाधान अभी भी शुरुआती तारीख को महीने के पहले तक समायोजित करके बचाया जा सकता है, उदाहरण के लिए।
CS

2
यह एक अच्छा समाधान है और यह मुझे बहुत समय बचाता है। हम शुरुआत की तारीख देकर इसे और बेहतर बना सकते हैं[dt for dt in rrule(MONTHLY, bymonthday=10,dtstart=strt_dt, until=end_dt)]
पेंग्जू झाओ जूल

1
इसके प्रति सजग रहें। उनके पास वास्तव में दस्तावेज़ीकरण में एक नोट है, जिसमें कहा गया है कि रुरल का "आश्चर्यजनक व्यवहार हो सकता है जब, उदाहरण के लिए, महीने के अंत में शुरुआत की तारीख होती है" (देखें dateutil.readthedocs.io/en/stable/rrule.html में नोट )। इससे बचने का एक तरीका यह है कि महीने के पहले दिन की तारीखों को बदल दिया जाए: start_date_first = start_date.replace(day=1), end_date_first = end_date.replace(day=1)फिर रूल ठीक से महीनों की गिनती करता है।
अल्ला सोरोकिना

36

यह मेरे लिए काम किया -

from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime('2011-08-15 12:00:00', '%Y-%m-%d %H:%M:%S')
date2 = datetime.strptime('2012-02-15', '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months + (12*r.years)

str()स्ट्रिंग शाब्दिक के आसपास अनावश्यक हटा दें ।
jfs

7
लायक कुछ भी नहीं है कि यदि डेल्टा 1 वर्ष से अधिक है, r.monthsतो 0 से शुरू होगा
jbkkd

2
आमतौर पर मैं r.months * (r.years + 1) करता हूं, क्योंकि @jbkkd किस बारे में बात कर रहा था, इसके लिए समायोजन करता है
triunenature

9
@triunenature यह गलत लगता है, निश्चित रूप से यह r.months + (r.years * 12) जैसा कुछ होना चाहिए
Moataz Elmasry

2
यदि दिनांक एक वर्ष से अधिक हैं, तो हाँ, यह काम नहीं करता है।
हंसजी 600

11

आप इसे आसानी से खजूर के मॉड्यूल से रल का उपयोग करके गणना कर सकते हैं :

from dateutil import rrule
from datetime import date

print(list(rrule.rrule(rrule.MONTHLY, dtstart=date(2013, 11, 1), until=date(2014, 2, 1))))

तुम्हे दूंगा:

 [datetime.datetime(2013, 11, 1, 0, 0),
 datetime.datetime(2013, 12, 1, 0, 0),
 datetime.datetime(2014, 1, 1, 0, 0),
 datetime.datetime(2014, 2, 1, 0, 0)]

10

समाप्त होने वाले महीने को प्राप्त करें (प्रारंभ माह के वर्ष और महीने के सापेक्ष पूर्व: 2011 जनवरी = 13 यदि आपकी प्रारंभ तिथि 2010 अक्टूबर को शुरू होती है) और फिर आरंभ माह शुरू करने वाले डेटाइम को उत्पन्न करें और इस तरह अंत माह:

dt1, dt2 = dateRange
start_month=dt1.month
end_months=(dt2.year-dt1.year)*12 + dt2.month+1
dates=[datetime.datetime(year=yr, month=mn, day=1) for (yr, mn) in (
          ((m - 1) / 12 + dt1.year, (m - 1) % 12 + 1) for m in range(start_month, end_months)
      )]

यदि दोनों तिथियां एक ही वर्ष में हैं, तो इसे केवल इस प्रकार लिखा जा सकता है:

dates=[datetime.datetime(year=dt1.year, month=mn, day=1) for mn in range(dt1.month, dt2.month + 1)]

8

यह पोस्ट यह नाखून! का उपयोग करें dateutil.relativedelta

from datetime import datetime
from dateutil import relativedelta
date1 = datetime.strptime(str('2011-08-15 12:00:00'), '%Y-%m-%d %H:%M:%S')
date2 = datetime.strptime(str('2012-02-15'), '%Y-%m-%d')
r = relativedelta.relativedelta(date2, date1)
r.months

1
@edouard जैसा कि आप मेरे द्वारा दिए गए उदाहरण में देख सकते हैं, तिथियां विभिन्न वर्षों में हैं। बहरहाल, str()मैंने जो कास्ट किया वह पूरी तरह से अनावश्यक है।
srodriguex

5
इस यदि दिनांक एक साल से अधिक को कवर काम नहीं करता है, तो आप जोड़ने की जरूरत हैrelativedelta.relativedelta(date2, date1).years * 12
muon

delta.years*12 + delta.months
user2682863

7

मेरा सरल समाधान:

import datetime

def months(d1, d2):
    return d1.month - d2.month + 12*(d1.year - d2.year)

d1 = datetime.datetime(2009, 9, 26)  
d2 = datetime.datetime(2019, 9, 26) 

print(months(d1, d2))

अंडर सराहना समाधान
reabow

4

परिभाषित एक "महीने" के रूप में 1 / 12 साल है, तो इस कार्य करें:

def month_diff(d1, d2): 
    """Return the number of months between d1 and d2, 
    such that d2 + month_diff(d1, d2) == d1
    """
    diff = (12 * d1.year + d1.month) - (12 * d2.year + d2.month)
    return diff

आप एक महीने को "29, 28, 30 या 31 दिनों (वर्ष के आधार पर)" की अवधि के रूप में परिभाषित करने का प्रयास कर सकते हैं। लेकिन आप ऐसा करते हैं, आपको हल करने के लिए एक अतिरिक्त समस्या है।

हालांकि यह आम तौर पर स्पष्ट है कि जून 15 वें + 1 महीने होना चाहिए जुलाई 15 वें , है ना आमतौर पर नहीं स्पष्ट है अगर जनवरी 30 वें + 1 महीने फरवरी या मार्च में है। उत्तरार्द्ध मामले में, यदि आप फरवरी में 30 तारीख की गणना करने के लिए मजबूर किया जा सकता है वें 2 मार्च तक है, तो "सही" यह nd । लेकिन जब आप ऐसा करते हैं, आप मिल जाएगा 2 मार्च के nd - 1 महीने स्पष्ट रूप से 2 फ़रवरी nd । एर्गो, रिडक्टियो एड एब्सर्डम (यह ऑपरेशन अच्छी तरह से परिभाषित नहीं है)।


4

360 दिन वर्षों पर आधारित एक सरल समाधान है, जहां सभी महीनों में 30 दिन होते हैं। यह ज्यादातर उपयोग के मामलों में फिट बैठता है, जहां दो तिथियां दी जाती हैं, आपको पूरे महीने की संख्या और शेष दिनों की गणना करने की आवश्यकता होती है।

from datetime import datetime, timedelta

def months_between(start_date, end_date):
    #Add 1 day to end date to solve different last days of month 
    s1, e1 = start_date , end_date  + timedelta(days=1)
    #Convert to 360 days
    s360 = (s1.year * 12 + s1.month) * 30 + s1.day
    e360 = (e1.year * 12 + e1.month) * 30 + e1.day
    #Count days between the two 360 dates and return tuple (months, days)
    return divmod(e360 - s360, 30)

print "Counting full and half months"
print months_between( datetime(2012, 01, 1), datetime(2012, 03, 31)) #3m
print months_between( datetime(2012, 01, 1), datetime(2012, 03, 15)) #2m 15d
print months_between( datetime(2012, 01, 16), datetime(2012, 03, 31)) #2m 15d
print months_between( datetime(2012, 01, 16), datetime(2012, 03, 15)) #2m
print "Adding +1d and -1d to 31 day month"
print months_between( datetime(2011, 12, 01), datetime(2011, 12, 31)) #1m 0d
print months_between( datetime(2011, 12, 02), datetime(2011, 12, 31)) #-1d => 29d
print months_between( datetime(2011, 12, 01), datetime(2011, 12, 30)) #30d => 1m
print "Adding +1d and -1d to 29 day month"
print months_between( datetime(2012, 02, 01), datetime(2012, 02, 29)) #1m 0d
print months_between( datetime(2012, 02, 02), datetime(2012, 02, 29)) #-1d => 29d
print months_between( datetime(2012, 02, 01), datetime(2012, 02, 28)) #28d
print "Every month has 30 days - 26/M to 5/M+1 always counts 10 days"
print months_between( datetime(2011, 02, 26), datetime(2011, 03, 05))
print months_between( datetime(2012, 02, 26), datetime(2012, 03, 05))
print months_between( datetime(2012, 03, 26), datetime(2012, 04, 05))

4

@ विन-जी द्वारा कुछ हद तक एक छोटा सा समाधान।

import datetime

def monthrange(start, finish):
  months = (finish.year - start.year) * 12 + finish.month + 1 
  for i in xrange(start.month, months):
    year  = (i - 1) / 12 + start.year 
    month = (i - 1) % 12 + 1
    yield datetime.date(year, month, 1)

4

आप तीर पुस्तकालय का उपयोग भी कर सकते हैं । यह एक सरल उदाहरण है:

from datetime import datetime
import arrow

start = datetime(2014, 1, 17)
end = datetime(2014, 6, 20)

for d in arrow.Arrow.range('month', start, end):
    print d.month, d.format('MMMM')

यह प्रिंट करेगा:

1 January
2 February
3 March
4 April
5 May
6 June

उम्मीद है की यह मदद करेगा!


4
from dateutil import relativedelta

relativedelta.relativedelta(date1, date2)

months_difference = (r.years * 12) + r.months

3

कुछ इस तरह की कोशिश करो। इसमें वर्तमान में वह महीना शामिल है यदि दोनों तिथियां एक ही महीने में हों।

from datetime import datetime,timedelta

def months_between(start,end):
    months = []
    cursor = start

    while cursor <= end:
        if cursor.month not in months:
            months.append(cursor.month)
        cursor += timedelta(weeks=1)

    return months

आउटपुट जैसा दिखता है:

>>> start = datetime.now() - timedelta(days=120)
>>> end = datetime.now()
>>> months_between(start,end)
[6, 7, 8, 9, 10]

यह अभी भी एक ही लूपिंग दृष्टिकोण लेता है, इसलिए मुझे जरूरी फायदा नहीं दिखता ...
जोशकुंज

1
मैं नहीं देखता कि यह कैसे समस्या है। लूप्स आपके दुश्मन नहीं हैं।
चार्ल्स हूपर

खैर यह हर बार किया गया है जब उनकी अजाक्स क्वेरी है। मुझे पता है कि लूप दुश्मन नहीं हैं, लेकिन ऐसा लगता है कि वे एक समस्या का धीमा समाधान हैं जिसे बहुत आसान तरीके से हल किया जाना चाहिए।
जोशकुंज


3

पांडस एफडब्ल्यूआईडब्ल्यू के साथ ऐसा करने का तरीका यहां दिया गया है:

import pandas as pd
pd.date_range("1990/04/03", "2014/12/31", freq="MS")

DatetimeIndex(['1990-05-01', '1990-06-01', '1990-07-01', '1990-08-01',
               '1990-09-01', '1990-10-01', '1990-11-01', '1990-12-01',
               '1991-01-01', '1991-02-01',
               ...
               '2014-03-01', '2014-04-01', '2014-05-01', '2014-06-01',
               '2014-07-01', '2014-08-01', '2014-09-01', '2014-10-01',
               '2014-11-01', '2014-12-01'],
              dtype='datetime64[ns]', length=296, freq='MS')

ध्यान दें कि यह दी गई आरंभ तिथि के बाद के महीने से शुरू होता है ।


2

यह datetime.timedelta का उपयोग करके किया जा सकता है, जहां अगले महीने स्किप करने के लिए दिनों की संख्या calender.monthrange द्वारा प्राप्त की जा सकती है। महीने की व्यवस्था सप्ताह के दिन (0-6 ~ सोम-सूर्य) और किसी दिए गए वर्ष और महीने के लिए दिनों की संख्या (28-31) है।
उदाहरण के लिए: प्रति माह (2017, 1) रिटर्न (6,31)।

दो महीनों के बीच इस तर्क का उपयोग करने वाली स्क्रिप्ट इस प्रकार है।

from datetime import timedelta
import datetime as dt
from calendar import monthrange

def month_iterator(start_month, end_month):
    start_month = dt.datetime.strptime(start_month,
                                   '%Y-%m-%d').date().replace(day=1)
    end_month = dt.datetime.strptime(end_month,
                                 '%Y-%m-%d').date().replace(day=1)
    while start_month <= end_month:
        yield start_month
        start_month = start_month + timedelta(days=monthrange(start_month.year, 
                                                         start_month.month)[1])

`


क्या आप बता सकते हैं कि यह कैसे समस्या को हल करता है? हम लोगों को उनके उत्तरों के संदर्भ में जोड़ने के लिए प्रोत्साहित करते हैं; धन्यवाद।
Gi0rgi0s

1
जोड़ा स्पष्टीकरण
कुमार

2

कई लोगों ने आपको इसे हल करने के लिए पहले ही अच्छे उत्तर दे दिए हैं, लेकिन मैंने सूची बोध का उपयोग करते हुए नहीं पढ़ा है, इसलिए मैं आपको एक समान उपयोग के मामले में क्या देता हूं:


def compute_months(first_date, second_date):
    year1, month1, year2, month2 = map(
        int, 
        (first_date[:4], first_date[5:7], second_date[:4], second_date[5:7])
    )

    return [
        '{:0>4}-{:0>2}'.format(year, month)
        for year in range(year1, year2 + 1)
        for month in range(month1 if year == year1 else 1, month2 + 1 if year == year2 else 13)
    ]

>>> first_date = "2016-05"
>>> second_date = "2017-11"
>>> compute_months(first_date, second_date)
['2016-05',
 '2016-06',
 '2016-07',
 '2016-08',
 '2016-09',
 '2016-10',
 '2016-11',
 '2016-12',
 '2017-01',
 '2017-02',
 '2017-03',
 '2017-04',
 '2017-05',
 '2017-06',
 '2017-07',
 '2017-08',
 '2017-09',
 '2017-10',
 '2017-11']

1
#This definition gives an array of months between two dates.
import datetime
def MonthsBetweenDates(BeginDate, EndDate):
    firstyearmonths = [mn for mn in range(BeginDate.month, 13)]<p>
    lastyearmonths = [mn for mn in range(1, EndDate.month+1)]<p>
    months = [mn for mn in range(1, 13)]<p>
    numberofyearsbetween = EndDate.year - BeginDate.year - 1<p>
    return firstyearmonths + months * numberofyearsbetween + lastyearmonths<p>

#example
BD = datetime.datetime.strptime("2000-35", '%Y-%j')
ED = datetime.datetime.strptime("2004-200", '%Y-%j')
MonthsBetweenDates(BD, ED)

1

rangeफ़ंक्शन की तरह , जब माह 13 है , तो अगले वर्ष पर जाएं

def year_month_range(start_date, end_date):
    '''
    start_date: datetime.date(2015, 9, 1) or datetime.datetime
    end_date: datetime.date(2016, 3, 1) or datetime.datetime
    return: datetime.date list of 201509, 201510, 201511, 201512, 201601, 201602
    '''
    start, end = start_date.strftime('%Y%m'), end_date.strftime('%Y%m')
    assert len(start) == 6 and len(end) == 6
    start, end = int(start), int(end)

    year_month_list = []
    while start < end:
        year, month = divmod(start, 100)
        if month == 13:
            start += 88  # 201513 + 88 = 201601
            continue
        year_month_list.append(datetime.date(year, month, 1))

        start += 1
    return year_month_list

अजगर के खोल में उदाहरण

>>> import datetime
>>> s = datetime.date(2015,9,1)
>>> e = datetime.date(2016, 3, 1)
>>> year_month_set_range(s, e)
[datetime.date(2015, 11, 1), datetime.date(2015, 9, 1), datetime.date(2016, 1, 1), datetime.date(2016, 2, 1),
 datetime.date(2015, 12, 1), datetime.date(2015, 10, 1)]

1

आमतौर पर 90 दिन 3 महीने नहीं होते हैं, सिर्फ एक संदर्भ।

तो, अंत में, आपको यह जांचने की आवश्यकता है कि क्या +1 से महीने के काउंटर को जोड़ने के लिए दिन 15 से बड़े हैं। या बेहतर, आधे महीने के काउंटर के साथ एक और योगिनी जोड़ें।

से यह अन्य stackoverflow जवाब मैं अंत में उस के साथ समाप्त हो गया है:

#/usr/bin/env python
# -*- coding: utf8 -*-

import datetime
from datetime import timedelta
from dateutil.relativedelta import relativedelta
import calendar

start_date = datetime.date.today()
end_date = start_date + timedelta(days=111)
start_month = calendar.month_abbr[int(start_date.strftime("%m"))]

print str(start_date) + " to " + str(end_date)

months = relativedelta(end_date, start_date).months
days = relativedelta(end_date, start_date).days

print months, "months", days, "days"

if days > 16:
    months += 1

print "around " + str(months) + " months", "(",

for i in range(0, months):
    print calendar.month_abbr[int(start_date.strftime("%m"))],
    start_date = start_date + relativedelta(months=1)

print ")"

आउटपुट:

2016-02-29 2016-06-14
3 months 16 days
around 4 months ( Feb Mar Apr May )

मैंने देखा है कि यदि आप वर्तमान वर्ष में बचे दिनों से अधिक जोड़ते हैं तो यह काम नहीं करता है, और यह अप्रत्याशित है।


1

ऐसा लगता है कि उत्तर असंतोषजनक हैं और मेरे पास अपने स्वयं के कोड का उपयोग करने के लिए है जिसे समझना आसान है

from datetime import datetime
from dateutil import relativedelta

date1 = datetime.strptime(str('2017-01-01'), '%Y-%m-%d')
date2 = datetime.strptime(str('2019-03-19'), '%Y-%m-%d')

difference = relativedelta.relativedelta(date2, date1)
months = difference.months
years = difference.years
# add in the number of months (12) for difference in years
months += 12 * difference.years
months

1
from datetime import datetime
from dateutil import relativedelta

def get_months(d1, d2):
    date1 = datetime.strptime(str(d1), '%Y-%m-%d')
    date2 = datetime.strptime(str(d2), '%Y-%m-%d')
    print (date2, date1)
    r = relativedelta.relativedelta(date2, date1)
    months = r.months +  12 * r.years
    if r.days > 0:
        months += 1
    print (months)
    return  months


assert  get_months('2018-08-13','2019-06-19') == 11
assert  get_months('2018-01-01','2019-06-19') == 18
assert  get_months('2018-07-20','2019-06-19') == 11
assert  get_months('2018-07-18','2019-06-19') == 12
assert  get_months('2019-03-01','2019-06-19') == 4
assert  get_months('2019-03-20','2019-06-19') == 3
assert  get_months('2019-01-01','2019-06-19') == 6
assert  get_months('2018-09-09','2019-06-19') == 10

0

अपरडेट मान लेना हमेशा बाद में लोअरडेट की तुलना में होता है और दोनों ही डेटाइम.डेट ऑब्जेक्ट होते हैं:

if lowerDate.year == upperDate.year:
    monthsInBetween = range( lowerDate.month + 1, upperDate.month )
elif upperDate.year > lowerDate.year:
    monthsInBetween = range( lowerDate.month + 1, 12 )
    for year in range( lowerDate.year + 1, upperDate.year ):
        monthsInBetween.extend( range(1,13) )
    monthsInBetween.extend( range( 1, upperDate.month ) )

मैंने इसका पूरी तरह से परीक्षण नहीं किया है, लेकिन ऐसा लगता है कि यह चाल चलनी चाहिए।


0

यहाँ एक विधि है:

def months_between(start_dt, stop_dt):
    month_list = []
    total_months = 12*(stop_dt.year-start_dt.year)+(stop_dt.month-start_d.month)+1
    if total_months > 0:
        month_list=[ datetime.date(start_dt.year+int((start_dt+i-1)/12), 
                                   ((start_dt-1+i)%12)+1,
                                   1) for i in xrange(0,total_months) ]
    return month_list

यह पहली बार दो तिथियों के बीच के महीनों की कुल संख्या को सम्मिलित कर रहा है। फिर यह आधार के रूप में पहली तारीख का उपयोग करके एक सूची बनाता है और दिनांक ऑब्जेक्ट बनाने के लिए मोडुला अंकगणित करता है।


0

मैं वास्तव में अभी कुछ बहुत समान करने की जरूरत है

एक समारोह जो यह दर्शाता है tuples की सूची लौटाता लेखन समाप्त हो गया startऔर endहर महीने की तारीखों के दो सेट के बीच तो मैं बिक्री आदि की मासिक योग के लिए इसके बारे में पीछे से कुछ एसक्यूएल प्रश्नों लिख सकते हैं

मुझे यकीन है कि यह किसी ऐसे व्यक्ति द्वारा सुधारा जा सकता है जो जानता है कि वे क्या कर रहे हैं, लेकिन आशा है कि यह मदद करता है ...

लौटाया गया मूल्य इस प्रकार है (उदाहरण के लिए आज तक - 365 दिन आज तक)

[   (datetime.date(2013, 5, 1), datetime.date(2013, 5, 31)),
    (datetime.date(2013, 6, 1), datetime.date(2013, 6, 30)),
    (datetime.date(2013, 7, 1), datetime.date(2013, 7, 31)),
    (datetime.date(2013, 8, 1), datetime.date(2013, 8, 31)),
    (datetime.date(2013, 9, 1), datetime.date(2013, 9, 30)),
    (datetime.date(2013, 10, 1), datetime.date(2013, 10, 31)),
    (datetime.date(2013, 11, 1), datetime.date(2013, 11, 30)),
    (datetime.date(2013, 12, 1), datetime.date(2013, 12, 31)),
    (datetime.date(2014, 1, 1), datetime.date(2014, 1, 31)),
    (datetime.date(2014, 2, 1), datetime.date(2014, 2, 28)),
    (datetime.date(2014, 3, 1), datetime.date(2014, 3, 31)),
    (datetime.date(2014, 4, 1), datetime.date(2014, 4, 30)),
    (datetime.date(2014, 5, 1), datetime.date(2014, 5, 31))]

निम्नानुसार कोड (कुछ डिबग सामान है जिसे हटाया जा सकता है):

#! /usr/env/python
import datetime

def gen_month_ranges(start_date=None, end_date=None, debug=False):
    today = datetime.date.today()
    if not start_date: start_date = datetime.datetime.strptime(
        "{0}/01/01".format(today.year),"%Y/%m/%d").date()  # start of this year
    if not end_date: end_date = today
    if debug: print("Start: {0} | End {1}".format(start_date, end_date))

    # sense-check
    if end_date < start_date:
        print("Error. Start Date of {0} is greater than End Date of {1}?!".format(start_date, end_date))
        return None

    date_ranges = []  # list of tuples (month_start, month_end)

    current_year = start_date.year
    current_month = start_date.month

    while current_year <= end_date.year:
        next_month = current_month + 1
        next_year = current_year
        if next_month > 12:
            next_month = 1
            next_year = current_year + 1

        month_start = datetime.datetime.strptime(
            "{0}/{1}/01".format(current_year,
                                current_month),"%Y/%m/%d").date()  # start of month
        month_end = datetime.datetime.strptime(
            "{0}/{1}/01".format(next_year,
                                next_month),"%Y/%m/%d").date()  # start of next month
        month_end  = month_end+datetime.timedelta(days=-1)  # start of next month less one day

        range_tuple = (month_start, month_end)
        if debug: print("Month runs from {0} --> {1}".format(
            range_tuple[0], range_tuple[1]))
        date_ranges.append(range_tuple)

        if current_month == 12:
            current_month = 1
            current_year += 1
            if debug: print("End of year encountered, resetting months")
        else:
            current_month += 1
            if debug: print("Next iteration for {0}-{1}".format(
                current_year, current_month))

        if current_year == end_date.year and current_month > end_date.month:
            if debug: print("Final month encountered. Terminating loop")
            break

    return date_ranges


if __name__ == '__main__':
    print("Running in standalone mode. Debug set to True")
    from pprint import pprint
    pprint(gen_month_ranges(debug=True), indent=4)
    pprint(gen_month_ranges(start_date=datetime.date.today()+datetime.timedelta(days=-365),
                            debug=True), indent=4)

0

यह मानते हुए कि आप उस महीने के "अंश" को जानना चाहते हैं जो तारीखों में थे, जो मैंने किया था, फिर आपको थोड़ा और काम करने की आवश्यकता है।

from datetime import datetime, date
import calendar

def monthdiff(start_period, end_period, decimal_places = 2):
    if start_period > end_period:
        raise Exception('Start is after end')
    if start_period.year == end_period.year and start_period.month == end_period.month:
        days_in_month = calendar.monthrange(start_period.year, start_period.month)[1]
        days_to_charge = end_period.day - start_period.day+1
        diff = round(float(days_to_charge)/float(days_in_month), decimal_places)
        return diff
    months = 0
    # we have a start date within one month and not at the start, and an end date that is not
    # in the same month as the start date
    if start_period.day > 1:
        last_day_in_start_month = calendar.monthrange(start_period.year, start_period.month)[1]
        days_to_charge = last_day_in_start_month - start_period.day +1
        months = months + round(float(days_to_charge)/float(last_day_in_start_month), decimal_places)
        start_period = datetime(start_period.year, start_period.month+1, 1)

    last_day_in_last_month = calendar.monthrange(end_period.year, end_period.month)[1]
    if end_period.day != last_day_in_last_month:
        # we have lest days in the last month
        months = months + round(float(end_period.day) / float(last_day_in_last_month), decimal_places)
        last_day_in_previous_month = calendar.monthrange(end_period.year, end_period.month - 1)[1]
        end_period = datetime(end_period.year, end_period.month - 1, last_day_in_previous_month)

    #whatever happens, we now have a period of whole months to calculate the difference between

    if start_period != end_period:
        months = months + (end_period.year - start_period.year) * 12 + (end_period.month - start_period.month) + 1

    # just counter for any final decimal place manipulation
    diff = round(months, decimal_places)
    return diff

assert monthdiff(datetime(2015,1,1), datetime(2015,1,31)) == 1
assert monthdiff(datetime(2015,1,1), datetime(2015,02,01)) == 1.04
assert monthdiff(datetime(2014,1,1), datetime(2014,12,31)) == 12
assert monthdiff(datetime(2014,7,1), datetime(2015,06,30)) == 12
assert monthdiff(datetime(2015,1,10), datetime(2015,01,20)) == 0.35
assert monthdiff(datetime(2015,1,10), datetime(2015,02,20)) == 0.71 + 0.71
assert monthdiff(datetime(2015,1,31), datetime(2015,02,01)) == round(1.0/31.0,2) + round(1.0/28.0,2)
assert monthdiff(datetime(2013,1,31), datetime(2015,02,01)) == 12*2 + round(1.0/31.0,2) + round(1.0/28.0,2)

एक उदाहरण प्रदान करता है जो दो तिथियों के बीच महीनों की संख्या को सम्मिलित रूप से काम करता है, जिसमें प्रत्येक महीने का वह अंश भी शामिल होता है, जिसका अर्थ है कि आप यह काम कर सकते हैं कि 2015-01-20 और 2015-02-14 के बीच कितने महीने हैं , जहां जनवरी के महीने में तारीख का अंश जनवरी में दिनों की संख्या से निर्धारित होता है; या समान रूप से इस बात को ध्यान में रखते हुए कि फरवरी में दिनों की संख्या साल-दर-साल बदल सकती है।

मेरे संदर्भ के लिए, यह कोड github पर भी है - https://gist.github.com/andrewyager/6b9284a4f1cdb1779b10


0

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

 dateRange = [datetime.strptime(dateRanges[0], "%Y-%m-%d"),
             datetime.strptime(dateRanges[1], "%Y-%m-%d")]
delta_time = max(dateRange) - min(dateRange)
#Need to use min(dateRange).month to account for different length month
#Note that timedelta returns a number of days
delta_datetime = (datetime(1, min(dateRange).month, 1) + delta_time -
                           timedelta(days=1)) #min y/m/d are 1
months = ((delta_datetime.year - 1) * 12 + delta_datetime.month -
          min(dateRange).month)
print months

कोई फर्क नहीं पड़ता कि आप तारीखों को किस क्रम में इनपुट करते हैं, और यह महीने की लंबाई में अंतर को ध्यान में रखता है।


ध्यान दें कि यह आपकी तारीखों के लिए समान नहीं है। सबसे आसान तरीका यह होगा कि अगर delta_time.days = 0: महीने = 0 बाकी की दिनचर्या हो।
om_henners

0

यह काम...

from datetime import datetime as dt
from dateutil.relativedelta import relativedelta
def number_of_months(d1, d2):
    months = 0
    r = relativedelta(d1,d2)
    if r.years==0:
        months = r.months
    if r.years>=1:
        months = 12*r.years+r.months
    return months
#example 
number_of_months(dt(2017,9,1),dt(2016,8,1))

0
from datetime import datetime

def diff_month(start_date,end_date):
    qty_month = ((end_date.year - start_date.year) * 12) + (end_date.month - start_date.month)

    d_days = end_date.day - start_date.day

    if d_days >= 0:
        adjust = 0
    else:
        adjust = -1
    qty_month += adjust

    return qty_month

diff_month(datetime.date.today(),datetime(2019,08,24))


#Examples:
#diff_month(datetime(2018,02,12),datetime(2019,08,24)) = 18
#diff_month(datetime(2018,02,12),datetime(2018,08,10)) = 5
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.