파이썬에서 날짜 범위 만들기


373

오늘부터 100 일까지 임의의 일 수로 돌아가는 날짜 목록을 만들고 싶습니다. 이것보다 더 좋은 방법이 있습니까?

import datetime

a = datetime.datetime.today()
numdays = 100
dateList = []
for x in range (0, numdays):
    dateList.append(a - datetime.timedelta(days = x))
print dateList

답변:


458

조금 더 나은 ...

base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]

6
시간대 인식 날짜 시간을 사용하고 DST가 이동하면 작동하지 않습니다! 내 말은, 당신이 시작과 끝 날짜를 사용 하여이 방법 사이에
채우면

@ s-lott range(0, numdays)이 경우 에만 사용할 수 없습니까?
Lukas Juhrich

3
나는이 방법을 약간 다른 방식으로 사용하여 10 분, 5 분 간격, +/- 일부 값 (제 경우에는 30 초)을 생성했습니다. 방금 공유 할 것이라고 생각했습니다 : datetimes = [start + timedelta(seconds=x*60+randint(-30, 30)) for x in range (0, range_end*5, 5)]변수range_end = 10
MikeyE

246

Pandas 일반적으로 시계열에 적합하며 날짜 범위를 직접 지원합니다.

예를 들면 pd.date_range()다음과 같습니다.

import pandas as pd
from datetime import datetime

datelist = pd.date_range(datetime.today(), periods=100).tolist()

또한 인생을 편하게 해주는 많은 옵션이 있습니다. 예를 들어 평일 만 원한다면로 바꾸면됩니다 bdate_range.

날짜 범위 설명서를 참조하십시오

또한 pytz 시간대를 완벽하게 지원하며 스프링 / 가을 DST 시프트에 부드럽게 적용 할 수 있습니다.

OP로 수정 :

Pandas 타임 스탬프와 달리 실제 파이썬 날짜 시간이 필요한 경우 :

import pandas as pd
from datetime import datetime

pd.date_range(end = datetime.today(), periods = 100).to_pydatetime().tolist()

#OR

pd.date_range(start="2018-09-09",end="2020-02-02")

"end"매개 변수를 사용하여 원래 질문과 일치하지만 내림차순 날짜를 원하는 경우 :

pd.date_range(datetime.today(), periods=100).to_pydatetime().tolist()

22
팬더가 이미 사용중인 경우 가장 좋은 답변은 Defo입니다. 내가 추가 할 유일한 것은 원래 게시물에 따라 날짜가 뒤로 이동하는 경우 end = 매개 변수를 사용한다는 것입니다. pd.date_range (end = pd.datetime.today (), periods = 100) .tolist ()
Thomas Browne

5
이 메소드의 한 가지 문제점은 Python Datetime 유형이 필요한 경우입니다. Pandas 또는 numpy 날짜 범위 메소드를 사용하면 Timestamp 및 Datetime64 유형이 작성 list(map(pd.Timestamp.to_pydatetime, datelist))됩니다. ... Datetime 유형을 다시
가져와야합니다

pandas.datetime클래스는 더 이상 사용되지 않으며 향후 버전에서는 팬더에서 제거됩니다. datetime대신 모듈 에서 가져옵니다 .
Trenton McKinney

82

지정된 시작 날짜와 종료 날짜 사이의 날짜 범위를 가져옵니다 (시간 및 공간 복잡성에 최적화 됨).

import datetime

start = datetime.datetime.strptime("21-06-2014", "%d-%m-%Y")
end = datetime.datetime.strptime("07-07-2014", "%d-%m-%Y")
date_generated = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]

for date in date_generated:
    print date.strftime("%d-%m-%Y")

6
초기 제안은 [] 대신 ()를 사용하여 date_generator를 얻는 것입니다. 의미에서 효율적으로 전체 날짜 배열을 저장하고 필요할 때만 날짜를 생성 할 필요가 없습니다.
Sandeep

2
end_date는 생성되지 않습니다.
Thorbjørn Ravn Andersen

8
종료 날짜를 얻으려면 (end-start + 1)을 사용하십시오.
Sandeep

6
OP의 질문에 대답하지는 않지만 그것이 내가
Thierry J.

2
(end-start+1)작동하지 않으면 timedelta와 int를 추가 할 수 없습니다. (end-start).days + 1그래도 사용할 수 있습니다 .
Stephen Paulger

44

오늘부터 시작하는 날짜 객체를 반환하는 생성기 함수를 작성할 수 있습니다.

import datetime

def date_generator():
  from_date = datetime.datetime.today()
  while True:
    yield from_date
    from_date = from_date - datetime.timedelta(days=1)

이 생성기는 오늘부터 시작하여 한 번에 하루 씩 거꾸로 날짜를 반환합니다. 처음 3 일을 취하는 방법은 다음과 같습니다.

>>> import itertools
>>> dates = itertools.islice(date_generator(), 3)
>>> list(dates)
[datetime.datetime(2009, 6, 14, 19, 12, 21, 703890), datetime.datetime(2009, 6, 13, 19, 12, 21, 703890), datetime.datetime(2009, 6, 12, 19, 12, 21, 703890)]

루프 또는 목록 이해에 비해이 방법의 장점은 원하는만큼 여러 번 되돌아 갈 수 있다는 것입니다.

편집하다

함수 대신 생성기 표현식을 사용하는보다 컴팩트 한 버전 :

date_generator = (datetime.datetime.today() - datetime.timedelta(days=i) for i in itertools.count())

용법:

>>> dates = itertools.islice(date_generator, 3)
>>> list(dates)
[datetime.datetime(2009, 6, 15, 1, 32, 37, 286765), datetime.datetime(2009, 6, 14, 1, 32, 37, 286836), datetime.datetime(2009, 6, 13, 1, 32, 37, 286859)]

1
일 수가 임의 인 경우 생성기를 사용하는 것이 이상적입니다.
xssChauhan

32

예, 바퀴를 재발 명하십시오 .... 포럼을 검색하면 다음과 같은 것을 얻을 수 있습니다 :

from dateutil import rrule
from datetime import datetime

list(rrule.rrule(rrule.DAILY,count=100,dtstart=datetime.now()))

22
labix.org/python-dateutil이 필요합니다 . 멋지게 보이지만 한 줄을 저장하는 것만으로는 외부 종속성의 가치가 거의 없습니다.
베니 체르니 아프 스키 파 스킨

1
다른 답변이 매우 비판적이라고 믿을 수 없습니다. rrule은 끔찍한 이름이지만 적어도 눈에는 쉽지 않습니다.
보트 코더 September

7
@ BeniCherniavsky-Paskin : 마침표 (달력) 산술을 구현하는 동안 미묘한 버그를 도입 하는 것은 매우 쉽습니다. dateutil.rrule구현 iCalendar는 RFC는 - 대신 이제까지 약간 차이가 거의 동일한 기능의 여러 구현의 잘 정의 된 행동 기능을 쉽게 사용할 수 있습니다. dateutil.rrule버그 수정을 한 곳으로 제한 할 수 있습니다.
jfs

3
@ Mark0978 : rrule이름은 임의적이지 않습니다. 해당 rfc
jfs

1
예, 불행한 이름 선택을 위해 dateutil을 비난하지 않았습니다. :-)
boatcoder

32

요일 서수를 사용하여 더 간단하게 만들 수도 있습니다.

def date_range(start_date, end_date):
    for ordinal in range(start_date.toordinal(), end_date.toordinal()):
        yield datetime.date.fromordinal(ordinal)

또는 의견에서 제안한 것처럼 다음과 같은 목록을 만들 수 있습니다.

date_range = [
    datetime.date.fromordinal(ordinal) 
    for ordinal in range(
        start_date.toordinal(),
        end_date.toordinal(),
    )
]

18

이 질문의 제목에서 나는 range()두 개의 날짜를 지정하고 사이에있는 모든 날짜가있는 목록을 만들 수있는 것과 같은 것을 찾을 것으로 기대했습니다 . 그렇게하면 미리 알 수없는 경우 두 날짜 사이의 일 수를 계산할 필요가 없습니다.

따라서 주제를 약간 벗어난 위험이 있기 때문에이 단일 라이너는 다음 작업을 수행합니다.

import datetime
start_date = datetime.date(2011, 01, 01)
end_date   = datetime.date(2014, 01, 01)

dates_2011_2013 = [ start_date + datetime.timedelta(n) for n in range(int ((end_date - start_date).days))]

이 답변에 대한 모든 크레딧 !


1
그것은 그 질문에 대한 다른 많은 대답보다 하나의 라이너가 아닙니다.
Thomas Browne

4
나는 이것이 다른 사람들의 대답보다 더 하나의 라이너라고 주장하지 않았으며, 이것이 더 나은 해결책이라고는 생각하지 않았습니다. 나는 당신이 요청한 것과 약간 다른 코드를 보여 주었지만 여기서 질문의 제목이 주어지면 기뻤을 것입니다.
snake_charmer

11

다음은 두 날짜 start와 사이의 날짜 목록을 제공하는 S.Lott의 답변에서 약간 다른 답변 end입니다. 아래 예에서 2017 년부터 오늘까지.

start = datetime.datetime(2017,1,1)
end = datetime.datetime.today()
daterange = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]

7

내가 아는 약간의 대답이지만 방금 같은 문제가 있었고 파이썬의 내부 범위 함수 가이 점에서 약간 부족하다고 결정했기 때문에 유틸리티 모듈에서 재정의했습니다.

from __builtin__ import range as _range
from datetime import datetime, timedelta

def range(*args):
    if len(args) != 3:
        return _range(*args)
    start, stop, step = args
    if start < stop:
        cmp = lambda a, b: a < b
        inc = lambda a: a + step
    else:
        cmp = lambda a, b: a > b
        inc = lambda a: a - step
    output = [start]
    while cmp(start, stop):
        start = inc(start)
        output.append(start)

    return output

print range(datetime(2011, 5, 1), datetime(2011, 10, 1), timedelta(days=30))

1
루프 output = []에서 줄을 바꾸고 싶다고 생각합니다 while cmp(...). range(0,10,1)와 비교하십시오 _range(0,10,1).
sigfpe

3
함수의 이름을 지정하면이 대답이 더 좋을 것이라고 생각합니다 date_range.
Brandon Bradley

7

내가 직접 작성한 답변을 기반으로 :

import datetime;
print [(datetime.date.today() - datetime.timedelta(days=x)).strftime('%Y-%m-%d') for x in range(-5, 0)]

산출:

['2017-12-11', '2017-12-10', '2017-12-09', '2017-12-08', '2017-12-07']

차이점은 ' date' 이 아니라 ' '객체를 얻는다는 datetime.datetime것입니다.


7

두 개의 날짜가 있고 범위가 필요한 경우

from dateutil import rrule, parser
date1 = '1995-01-01'
date2 = '1995-02-28'
datesx = list(rrule.rrule(rrule.DAILY, dtstart=parser.parse(date1), until=parser.parse(date2)))

5

내 자신의 코드에서 만든 요점이 여기에 도움이 될 수 있습니다. (질문이 너무 오래되었지만 다른 사람들이 사용할 수 있음)

https://gist.github.com/2287345

(아래 같은 것)

import datetime
from time import mktime

def convert_date_to_datetime(date_object):
    date_tuple = date_object.timetuple()
    date_timestamp = mktime(date_tuple)
    return datetime.datetime.fromtimestamp(date_timestamp)

def date_range(how_many=7):
    for x in range(0, how_many):
        some_date = datetime.datetime.today() - datetime.timedelta(days=x)
        some_datetime = convert_date_to_datetime(some_date.date())
        yield some_datetime

def pick_two_dates(how_many=7):
    a = b = convert_date_to_datetime(datetime.datetime.now().date())
    for each_date in date_range(how_many):
        b = a
        a = each_date
        if a == b:
            continue
        yield b, a

4

다음은 bash 스크립트가 평일 목록을 얻는 하나의 라이너입니다. 이것은 파이썬 3입니다.

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.today() - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int(sys.argv[1])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 10

시작일 (또는 오히려 종료일)을 제공하는 변형이 있습니다.

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d \") for x in range(0,int(sys.argv[2])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/30 10

다음은 임의의 시작 및 종료 날짜에 대한 변형입니다. 이것은 매우 효율적이지는 않지만 bash 스크립트에 for 루프를 넣는 데 좋습니다.

python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") + datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int((datetime.datetime.strptime(sys.argv[2], \"%Y/%m/%d\") - datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\")).days)) if (datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\") + datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/15 2015/12/30

댓글의 코드로 답변 게시물을 업데이트 할 수 있습니다. 파이썬은 주석에 엉망이되어서 약간의 서식이 필요합니다.
Jake Bathman

3

Matplotlib 관련

from matplotlib.dates import drange
import datetime

base = datetime.date.today()
end  = base + datetime.timedelta(days=100)
delta = datetime.timedelta(days=1)
l = drange(base, end, delta)

3

나는 이것이 대답되었다는 것을 알고 있지만, 역사적 목적을 위해 대답을 내려 놓을 것이며, 나는 그것이 직선이라고 생각하기 때문에.

import numpy as np
import datetime as dt
listOfDates=[date for date in np.arange(firstDate,lastDate,dt.timedelta(days=x))]

물론 코드 골프와 같은 것은 얻지 못하지만 우아하다고 생각합니다.


arange단계와는 아주 좋은,하지만 listOfDates구성 NumPy와 datetime64 대신 파이썬 기본 날짜 시간의.
F.Raab

2
그러나 numpy datetime64 대신 네이티브 파이썬 datetime np.arange(…).astype(dt.datetime)arange반환 하는 데 사용할 수 있습니다 .
F.Raab

2

Sandeep의 답변에서 시작하여 앞으로 또는 뒤로 계산하는 또 다른 예입니다.

from datetime import date, datetime, timedelta
from typing import Sequence
def range_of_dates(start_of_range: date, end_of_range: date) -> Sequence[date]:

    if start_of_range <= end_of_range:
        return [
            start_of_range + timedelta(days=x)
            for x in range(0, (end_of_range - start_of_range).days + 1)
        ]
    return [
        start_of_range - timedelta(days=x)
        for x in range(0, (start_of_range - end_of_range).days + 1)
    ]

start_of_range = datetime.today().date()
end_of_range = start_of_range + timedelta(days=3)
date_range = range_of_dates(start_of_range, end_of_range)
print(date_range)

준다

[datetime.date(2019, 12, 20), datetime.date(2019, 12, 21), datetime.date(2019, 12, 22), datetime.date(2019, 12, 23)]

start_of_range = datetime.today().date()
end_of_range = start_of_range - timedelta(days=3)
date_range = range_of_dates(start_of_range, end_of_range)
print(date_range)

준다

[datetime.date(2019, 12, 20), datetime.date(2019, 12, 19), datetime.date(2019, 12, 18), datetime.date(2019, 12, 17)]

시작 날짜는 반품에 포함되므로 총 4 개의 날짜를 원하면 timedelta(days=3)


1
from datetime import datetime, timedelta
from dateutil import parser
def getDateRange(begin, end):
    """  """
    beginDate = parser.parse(begin)
    endDate =  parser.parse(end)
    delta = endDate-beginDate
    numdays = delta.days + 1
    dayList = [datetime.strftime(beginDate + timedelta(days=x), '%Y%m%d') for x in range(0, numdays)]
    return dayList

1

와 월간 날짜 범위 발생기 datetimedateutil. 간단하고 이해하기 쉬운 :

import datetime as dt
from dateutil.relativedelta import relativedelta

def month_range(start_date, n_months):
        for m in range(n_months):
            yield start_date + relativedelta(months=+m)

0
import datetime    
def date_generator():
    cur = base = datetime.date.today()
    end  = base + datetime.timedelta(days=100)
    delta = datetime.timedelta(days=1)
    while(end>base):
        base = base+delta
        print base

date_generator()

1
(가) 그래서 그는 .. 전달하지, 다시 가고 싶어 end해야한다 base - datetime.timedelta. 또한 ... 왜이 솔루션이 원래 솔루션보다 나은가요?
frarugi87

0

위의 답변에서 날짜 생성기에 대한이 예제를 만들었습니다.

import datetime
date = datetime.datetime.now()
time = date.time()
def date_generator(date, delta):
  counter =0
  date = date - datetime.timedelta(days=delta)
  while counter <= delta:
    yield date
    date = date + datetime.timedelta(days=1)
    counter +=1

for date in date_generator(date, 30):
   if date.date() != datetime.datetime.now().date():
     start_date = datetime.datetime.combine(date, datetime.time())
     end_date = datetime.datetime.combine(date, datetime.time.max)
   else:
     start_date = datetime.datetime.combine(date, datetime.time())
     end_date = datetime.datetime.combine(date, time)
   print('start_date---->',start_date,'end_date---->',end_date)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.