Saya memiliki kebutuhan untuk dapat secara akurat menemukan bulan antara dua tanggal dengan python. Saya punya solusi yang berhasil tetapi tidak terlalu bagus (seperti elegan) atau cepat.
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
Jadi hanya untuk menjelaskan, yang saya lakukan di sini adalah mengambil dua tanggal dan mengubahnya dari format iso menjadi objek datetime python. Kemudian saya mengulang menambahkan satu minggu ke objek awal waktu dan memeriksa apakah nilai numerik bulan itu lebih besar (kecuali bulan itu Desember maka ia memeriksa apakah tanggalnya kurang), Jika nilainya lebih besar saya menambahkannya ke daftar bulan dan terus berulang sampai saya mencapai tanggal akhir saya.
Ini bekerja dengan sempurna hanya saja sepertinya bukan cara yang baik untuk melakukannya ...
python
datetime
monthcalendar
date-math
Joshkunz
sumber
sumber
Jawaban:
Perbarui 2018-04-20: tampaknya OP @Joshkunz meminta untuk menemukan bulan mana di antara dua tanggal, alih-alih "berapa bulan" di antara dua tanggal. Jadi saya tidak yakin mengapa @JohnLaRooy diberi suara positif lebih dari 100 kali. @Joshkunz mengindikasikan dalam komentar di bawah pertanyaan awal dia menginginkan tanggal sebenarnya [atau bulan], alih-alih menemukan jumlah total bulan .
Jadi tampaknya pertanyaan itu diinginkan, antara dua tanggal
2018-04-11
sampai2018-06-01
Apr 2018, May 2018, June 2018
Dan bagaimana jika di antara
2014-04-11
ke2018-06-01
? Maka jawabannya adalahApr 2014, May 2014, ..., Dec 2014, Jan 2015, ..., Jan 2018, ..., June 2018
Jadi itulah mengapa saya memiliki kode semu berikut beberapa tahun yang lalu. Itu hanya menyarankan menggunakan dua bulan sebagai titik akhir dan mengulanginya, bertambah satu bulan pada satu waktu. @Joshkunz menyebutkan bahwa dia menginginkan "bulan" dan dia juga menyebutkan bahwa dia menginginkan "tanggal", tanpa mengetahui secara pasti, sulit untuk menulis kode yang tepat, tetapi idenya adalah menggunakan satu putaran sederhana untuk mengulang melalui titik akhir, dan bertambah satu bulan pada satu waktu.
Jawabannya 8 tahun lalu di tahun 2010:
Jika dijumlahkan seminggu, maka kira-kira akan melakukan pekerjaan 4,35 kali pekerjaan sesuai kebutuhan. Mengapa tidak hanya:
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)
hanya kode pseduo untuk saat ini, belum diuji, tetapi saya pikir ide di sepanjang baris yang sama akan berfungsi.
sumber
1
menjadi2
, dan kemudian2
ke3
nanti.Mulailah dengan menentukan beberapa kasus uji, kemudian Anda akan melihat bahwa fungsinya sangat sederhana dan tidak memerlukan putaran
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
Anda harus menambahkan beberapa kasus uji ke pertanyaan Anda, karena ada banyak kasus sudut potensial untuk dibahas - ada lebih dari satu cara untuk menentukan jumlah bulan antara dua tanggal.
sumber
Satu baris untuk menemukan daftar waktu, bertambah menurut bulan, antara dua tanggal.
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)]
sumber
[dt for dt in rrule(MONTHLY, bymonthday=10,dtstart=strt_dt, until=end_dt)]
start_date_first = start_date.replace(day=1), end_date_first = end_date.replace(day=1)
Kemudian aturan menghitung bulan dengan benar.Ini berhasil untuk saya -
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)
sumber
str()
sekitar string literal.r.months
akan mulai dari 0Anda dapat dengan mudah menghitung ini menggunakan aturan dari modul dateutil :
from dateutil import rrule from datetime import date print(list(rrule.rrule(rrule.MONTHLY, dtstart=date(2013, 11, 1), until=date(2014, 2, 1))))
akan memberimu:
[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)]
sumber
Dapatkan bulan akhir (relatif terhadap tahun dan bulan dari bulan mulai mis: 2011 Januari = 13 jika tanggal mulai Anda dimulai pada Oktober 2010) dan kemudian buat waktu tanggal mulai bulan awal dan bulan akhir seperti ini:
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) )]
jika kedua tanggal berada pada tahun yang sama, dapat juga ditulis sebagai:
dates=[datetime.datetime(year=dt1.year, month=mn, day=1) for mn in range(dt1.month, dt2.month + 1)]
sumber
Posting ini berhasil! Gunakan
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
sumber
str()
pemeran yang saya lakukan sama sekali tidak perlu.relativedelta.relativedelta(date2, date1).years * 12
delta.years*12 + delta.months
Solusi sederhana saya:
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))
sumber
from dateutil import relativedelta relativedelta.relativedelta(date1, date2) months_difference = (r.years * 12) + r.months
sumber
Mendefinisikan "bulan" sebagai 1 / 12 tahun, kemudian melakukan hal ini:
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
Anda dapat mencoba menentukan bulan sebagai "periode 29, 28, 30 atau 31 hari (tergantung tahun)". Tetapi jika Anda melakukannya, Anda memiliki masalah tambahan yang harus dipecahkan.
Sementara itu biasanya jelas bahwa Juni 15 th + 1 bulan harus Juli 15 th , itu tidak biasanya tidak jelas apakah 30 Jan th + 1 bulan adalah bulan Februari atau Maret. Dalam kasus terakhir, Anda dapat dipaksa untuk menghitung tanggal sebagai Februari 30 th , maka "benar" itu 2 Maret nd . Tetapi ketika Anda melakukannya, Anda akan menemukan bahwa 2 Mar nd - 1 bulan jelas Februari 2 nd . Ergo, reductio ad absurdum (operasi ini tidak ditentukan dengan baik).
sumber
Ada solusi sederhana berdasarkan 360 hari dalam setahun, di mana semua bulan memiliki 30 hari. Ini cocok untuk sebagian besar kasus penggunaan di mana, dengan dua tanggal, Anda perlu menghitung jumlah bulan penuh ditambah hari yang tersisa.
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))
sumber
Sedikit solusi prettified oleh @ Vin-G.
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)
sumber
Anda juga bisa menggunakan perpustakaan panah . Ini adalah contoh sederhana:
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')
Ini akan mencetak:
1 January 2 February 3 March 4 April 5 May 6 June
Semoga ini membantu!
sumber
Cobalah sesuatu seperti ini. Ini sekarang termasuk bulan jika kedua tanggal kebetulan berada di bulan yang sama.
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
Outputnya terlihat seperti:
>>> start = datetime.now() - timedelta(days=120) >>> end = datetime.now() >>> months_between(start,end) [6, 7, 8, 9, 10]
sumber
Anda bisa menggunakan python-dateutil . Lihat Python: Perbedaan 2 waktu dalam beberapa bulan
sumber
Berikut cara melakukan ini dengan Pandas FWIW:
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')
Perhatikan itu dimulai dengan bulan setelah tanggal mulai yang ditentukan.
sumber
Ini bisa dilakukan dengan menggunakan datetime.timedelta, di mana jumlah hari untuk melompat ke bulan berikutnya dapat diperoleh dengan calender.monthrange. monthrange mengembalikan hari kerja (0-6 ~ Sen-Ming) dan jumlah hari (28-31) untuk tahun dan bulan tertentu.
Misalnya: monthrange (2017, 1) mengembalikan (6,31).
Berikut ini skrip yang menggunakan logika ini untuk mengulang antara dua bulan.
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])
`
sumber
Banyak orang telah memberi Anda jawaban yang baik untuk menyelesaikan ini tetapi saya belum membaca menggunakan pemahaman daftar jadi saya memberi Anda apa yang saya gunakan untuk kasus penggunaan serupa:
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']
sumber
#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)
sumber
Sama seperti
range
fungsinya, saat bulan 13 , lanjutkan ke tahun depandef 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
contoh di shell python
>>> 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)]
sumber
Biasanya 90 hari BUKAN 3 bulan secara harfiah, hanya referensi.
Jadi, akhirnya, Anda perlu memeriksa apakah hari lebih besar dari 15 untuk menambahkan +1 ke penghitung bulan. atau lebih baik, tambahkan elif lain dengan penghitung setengah bulan.
Dari jawaban stackoverflow lainnya ini, saya akhirnya mengakhiri dengan itu:
#/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 ")"
Keluaran:
2016-02-29 2016-06-14 3 months 16 days around 4 months ( Feb Mar Apr May )
Saya perhatikan itu tidak berfungsi jika Anda menambahkan lebih dari hari yang tersisa di tahun ini, dan itu tidak terduga.
sumber
sepertinya jawabannya tidak memuaskan dan saya telah menggunakan kode saya sendiri yang lebih mudah dimengerti
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
sumber
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
sumber
Inilah solusi saya untuk ini:
def calc_age_months(from_date, to_date): from_date = time.strptime(from_date, "%Y-%m-%d") to_date = time.strptime(to_date, "%Y-%m-%d") age_in_months = (to_date.tm_year - from_date.tm_year)*12 + (to_date.tm_mon - from_date.tm_mon) if to_date.tm_mday < from_date.tm_mday: return age_in_months -1 else return age_in_months
Ini akan menangani beberapa kasus edge juga di mana perbedaan bulan antara 31 Des 2018 dan 1 Jan 2019 akan menjadi nol (karena perbedaannya hanya satu hari).
sumber
Dengan asumsi upperDate selalu lebih baru dari lowerDate dan keduanya adalah objek datetime.date:
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 ) )
Saya belum menguji ini secara menyeluruh, tetapi sepertinya itu harus melakukan trik.
sumber
Berikut adalah metodenya:
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
Ini pertama kali menghitung jumlah bulan antara dua tanggal, inklusif. Kemudian membuat daftar menggunakan tanggal pertama sebagai basis dan melakukan aritmatika modula untuk membuat objek tanggal.
sumber
Saya sebenarnya perlu melakukan sesuatu yang sangat mirip sekarang
Akhirnya menulis fungsi yang mengembalikan daftar tupel yang menunjukkan
start
danend
setiap bulan antara dua set tanggal sehingga saya bisa menulis beberapa kueri SQL di belakangnya untuk total penjualan bulanan, dll.Saya yakin ini dapat ditingkatkan oleh seseorang yang tahu apa yang mereka lakukan tetapi berharap ini membantu ...
Nilai yang dikembalikan terlihat sebagai berikut (menghasilkan hari ini - 365 hari hingga hari ini sebagai contoh)
[ (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))]
Kode sebagai berikut (memiliki beberapa hal debug yang dapat dihapus):
#! /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)
sumber
Dengan asumsi bahwa Anda ingin mengetahui "pecahan" dari bulan pada tanggal itu, yang saya lakukan, maka Anda perlu melakukan sedikit lebih banyak pekerjaan.
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)
memberikan contoh yang menghitung jumlah bulan antara dua tanggal secara inklusif, termasuk pecahan setiap bulan saat tanggal tersebut masuk. Ini berarti Anda dapat menghitung berapa bulan antara 2015-01-20 dan 2015-02-14 , dimana pecahan tanggal di bulan Januari ditentukan oleh jumlah hari di bulan Januari; atau dengan mempertimbangkan bahwa jumlah hari di bulan Februari dapat berubah dari tahun ke tahun.
Untuk referensi saya, kode ini juga ada di github - https://gist.github.com/andrewyager/6b9284a4f1cdb1779b10
sumber
Coba ini:
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
Tidak masalah urutan apa yang Anda masukkan tanggal, dan itu memperhitungkan perbedaan panjang bulan.
sumber
Ini bekerja...
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))
sumber