[python] 두 날짜 사이의 달을 찾는 가장 좋은 방법

파이썬에서 두 날짜 사이의 달을 정확하게 찾을 수 있어야합니다. 나는 작동하지만 그다지 좋지 않거나 (우아하게) 빠르지 않은 해결책이 있습니다.

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

설명하기 위해 여기서 제가하는 일은 두 개의 날짜를 가져 와서 iso 형식에서 파이썬 datetime 객체로 변환하는 것입니다. 그런 다음 시작 datetime 객체에 주를 추가하는 과정을 반복하고 월의 숫자 값이 더 큰지 확인합니다 (월이 12 월이 아니면 날짜가 더 적은지 확인합니다). 값이 더 크면 목록에 추가합니다. 종료 날짜에 도달 할 때까지 계속 반복합니다.

완벽하게 작동합니다. 좋은 방법이 아닌 것 같습니다.



답변

업데이트 2018-04-20 : OP @Joshkunz가 두 날짜 사이에 “몇 개월”이 아니라 두 날짜 사이에 있는 달 을 찾는 것을 요청한 것 같습니다 . 그래서 @JohnLaRooy가 왜 100 회 이상 찬성표를 받았는지 모르겠습니다. @Joshkunz는 원래 질문의 주석에서 총 개월 수를 찾는 대신 실제 날짜 (또는 개월)를 원한다고 표시했습니다 .

그래서 두 날짜 사이 2018-04-112018-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

그래서 몇 년 전에 다음과 같은 의사 코드를 사용했습니다. 단지 두 달을 끝점으로 사용하고 한 번에 한 달씩 증가하면서 반복하는 것을 제안했습니다. @Joshkunz는 “월”을 원했고 “날짜”를 원한다고 언급했습니다. 정확히 알지 못한 채 정확한 코드를 작성하기 어려웠지만 아이디어는 하나의 간단한 루프를 사용하여 끝점을 반복하는 것입니다. 한 번에 한 달씩 증가합니다.

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 코드로 테스트하지 않았지만 같은 줄의 아이디어가 작동 할 것이라고 생각합니다.


답변

몇 가지 테스트 케이스를 정의하여 시작하면 함수가 매우 간단하고 루프가 필요하지 않음을 알 수 있습니다.

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

다룰 잠재적 인 코너 케이스가 많기 때문에 질문에 몇 가지 테스트 케이스를 추가해야합니다. 두 날짜 사이의 개월 수를 정의하는 방법은 여러 가지가 있습니다.


답변

두 날짜 사이에 월 단위로 증가하는 날짜 / 시간 목록을 찾기위한 라이너 하나.

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


답변

이것은 나를 위해 일했습니다-

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)


답변

dateutil 모듈의 rrule을 사용하여 쉽게 계산할 수 있습니다 .

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


답변

종료 월 (시작 월의 연도 및 월에 상대적인 예 : 시작 날짜가 2010 년 10 월에 시작하는 경우 2011 년 1 월 = 13)을 가져온 다음 다음과 같이 시작 월과 종료 월을 시작하는 날짜 시간을 생성합니다.

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


답변

이 포스트는 그것을 잘한다! 사용 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