source

Python에서 날짜 범위 만들기

goodcode 2022. 9. 4. 15:01
반응형

Python에서 날짜 범위 만들기

오늘부터 시작해서 임의의 일수(예: 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

조금 더 나은...

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

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

예를 들어 다음과 같습니다.

import pandas as pd
from datetime import datetime

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

그것은 또한 삶을 더 쉽게 만들 수 있는 많은 선택권을 가지고 있다.예를 들어 평일만 원하는 경우 스왑인하면 됩니다.

날짜 범위 문서 참조

또한 Pyz 타임존을 완전히 지원하며 봄/가을 DST 시프트를 부드럽게 스팬할 수 있습니다.

OP에 의한 편집:

Panda 타임스탬프가 아닌 실제 python 데이터타임이 필요한 경우:

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

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

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

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

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

그래, 수레바퀴를 재창조하고...포럼을 검색하기만 하면 다음과 같은 정보가 나타납니다.

from dateutil import rrule
from datetime import datetime

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

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

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

것을 수 있을 줄 요.range()2개의 날짜를 지정하고 그 사이에 모든 날짜를 포함하는 목록을 작성할 수 있습니다.미리 알지 못하면 두 날짜 사이의 일수를 계산할 필요가 없다.

따라서 주제에서 약간 벗어날 위험이 있지만, 이 원라이너는 다음과 같은 작업을 수행합니다.

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

답변에 대한 모든 크레딧!

여기 S에서 작성한 약간 다른 답변이 있습니다. 하는 Lott의start ★★★★★★★★★★★★★★★★★」end2017년입니다.

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

날짜가 두 개이고 범위가 필요한 경우 시도해 보십시오.

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

제가 직접 쓴 답변에 따르면 다음과 같습니다.

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'1'

조금 늦은 답변이지만, 같은 문제가 있어서 Python의 내부 범위 함수가 조금 부족하다고 판단했기 때문에 util 모듈에서 덮어썼습니다.

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

제 코드로 작성한 요지는 다음과 같습니다.(질문이 너무 오래된 것은 알지만 다른 사람이 사용할 수 있습니다.)

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

이것은 평일 목록을 얻기 위한 bash 스크립트용 라이너입니다.이것은 python 3 입니다.원하는 날짜에 따라 쉽게 변경할 수 있는 마지막 int는 원하는 과거 일수입니다.

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

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)

답이 나왔다는 것은 알지만, 역사적 목적을 위해, 그리고 저는 그것이 직설적이라고 생각하기 때문에, 제 대답을 적어두겠습니다.

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

코드 골프 같은 건 못 이기겠지만 우아한 것 같아요.

파라미터화된 창 크기(일, 분, 시간, 초)로 날짜 범위를 작성할 수 있는 일반적인 방법:

from datetime import datetime, timedelta

def create_date_ranges(start, end, **interval):
    start_ = start
    while start_ < end:
        end_ = start_ + timedelta(**interval)
        yield (start_, min(end_, end))
        start_ = end_

테스트:

def main():
    tests = [
        ('2021-11-15:00:00:00', '2021-11-17:13:00:00', {'days': 1}),
        ('2021-11-15:00:00:00', '2021-11-16:13:00:00', {'hours': 12}),
        ('2021-11-15:00:00:00', '2021-11-15:01:45:00', {'minutes': 30}),
        ('2021-11-15:00:00:00', '2021-11-15:00:01:12', {'seconds': 30})
    ]
    for t in tests:
        print("\nInterval: %s, range(%s to %s)" % (t[2], t[0], t[1]))
        start = datetime.strptime(t[0], '%Y-%m-%d:%H:%M:%S')
        end =  datetime.strptime(t[1], '%Y-%m-%d:%H:%M:%S')
        ranges = list(create_date_ranges(start, end, **t[2]))        
        x = list(map(
            lambda x: (x[0].strftime('%Y-%m-%d:%H:%M:%S'), x[1].strftime('%Y-%m-%d:%H:%M:%S')),
            ranges
        ))
        print(x)
main()

테스트 출력:

Interval: {'days': 1}, range(2021-11-15:00:00:00 to 2021-11-17:13:00:00)
[('2021-11-15:00:00:00', '2021-11-16:00:00:00'), ('2021-11-16:00:00:00', '2021-11-17:00:00:00'), ('2021-11-17:00:00:00', '2021-11-17:13:00:00')]

Interval: {'hours': 12}, range(2021-11-15:00:00:00 to 2021-11-16:13:00:00)
[('2021-11-15:00:00:00', '2021-11-15:12:00:00'), ('2021-11-15:12:00:00', '2021-11-16:00:00:00'), ('2021-11-16:00:00:00', '2021-11-16:12:00:00'), ('2021-11-16:12:00:00', '2021-11-16:13:00:00')]

Interval: {'minutes': 30}, range(2021-11-15:00:00:00 to 2021-11-15:01:45:00)
[('2021-11-15:00:00:00', '2021-11-15:00:30:00'), ('2021-11-15:00:30:00', '2021-11-15:01:00:00'), ('2021-11-15:01:00:00', '2021-11-15:01:30:00'), ('2021-11-15:01:30:00', '2021-11-15:01:45:00')]

Interval: {'seconds': 30}, range(2021-11-15:00:00:00 to 2021-11-15:00:01:12)
[('2021-11-15:00:00:00', '2021-11-15:00:00:30'), ('2021-11-15:00:00:30', '2021-11-15:00:01:00'), ('2021-11-15:00:01:00', '2021-11-15:00:01:12')]

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)

from datetime import datetime , timedelta, timezone


start_date = '2022_01_25'
end_date = '2022_01_30'

start = datetime.strptime(start_date, "%Y_%m_%d")
print(type(start))
end =  datetime.strptime(end_date, "%Y_%m_%d")
##pDate = str(pDate).replace('-', '_')
number_of_days = (end - start).days

print("number_of_days: ", number_of_days)

##
date_list = []
for day in range(number_of_days):
    a_date = (start + timedelta(days = day)).astimezone(timezone.utc)
    a_date = a_date.strftime('%Y-%m-%d')
    date_list.append(a_date)

print(date_list)

월별 날짜 범위 생성기:datetime그리고.dateutil·심플하고 알기 쉬운 것:

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

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

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)

날짜 범위의 간단한 구현(완전하지는 않음)에 대해 의견을 제시하려고 합니다.

from datetime import date, timedelta, datetime

class DateRange:
    def __init__(self, start, end, step=timedelta(1)):
        self.start = start
        self.end = end
        self.step = step

    def __iter__(self):
        start = self.start
        step = self.step
        end = self.end

        n = int((end - start) / step)
        d = start

        for _ in range(n):
            yield d
            d += step

    def __contains__(self, value):
        return (
            (self.start <= value < self.end) and 
            ((value - self.start) % self.step == timedelta(0))
        )

언급URL : https://stackoverflow.com/questions/993358/creating-a-range-of-dates-in-python

반응형