给定一个日期范围,我们如何将其分解为 N 个连续的子区间?

新手上路,请多包涵

我正在通过 API 访问一些数据,我需要在其中提供请求的日期范围,例如。开始=‘20100101’,结束=‘20150415’。我想我会通过将日期范围分解为不重叠的时间间隔并在每个时间间隔上使用多处理来加快速度。

我的问题是我打破日期范围的方式并没有始终如一地给我预期的结果。这是我所做的:

 from datetime import date

begin = '20100101'
end = '20101231'

假设我们想把它分成几个部分。首先,我将字符串更改为日期:

 def get_yyyy_mm_dd(yyyymmdd):
    # given string 'yyyymmdd' return (yyyy, mm, dd)
    year = yyyymmdd[0:4]
    month = yyyymmdd[4:6]
    day = yyyymmdd[6:]
    return int(year), int(month), int(day)

y1, m1, d1 = get_yyyy_mm_dd(begin)
d1 = date(y1, m1, d1)
y2, m2, d2 = get_yyyy_mm_dd(end)
d2 = date(y2, m2, d2)

然后将这个范围划分为子区间:

 def remove_tack(dates_list):
    # given a list of dates in form YYYY-MM-DD return a list of strings in form 'YYYYMMDD'
    tackless = []
    for d in dates_list:
        s = str(d)
        tackless.append(s[0:4]+s[5:7]+s[8:])
    return tackless

def divide_date(date1, date2, intervals):
    dates = [date1]
    for i in range(0, intervals):
        dates.append(dates[i] + (date2 - date1)/intervals)
    return remove_tack(dates)

使用上面的开始和结束我们得到:

 listdates = divide_date(d1, d2, 4)
print listdates # ['20100101', '20100402', '20100702', '20101001', '20101231'] looks correct

但如果我改为使用日期:

 begin = '20150101'
end = '20150228'

 listdates = divide_date(d1, d2, 4)
print listdates # ['20150101', '20150115', '20150129', '20150212', '20150226']

我在二月底错过了两天。我的应用程序不需要时间或时区,我不介意安装另一个库。

原文由 Scott 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 652
2 个回答

我实际上会采用不同的方法并依靠 timedelta 和 date 添加来确定非重叠范围

执行

def date_range(start, end, intv):
    from datetime import datetime
    start = datetime.strptime(start,"%Y%m%d")
    end = datetime.strptime(end,"%Y%m%d")
    diff = (end  - start ) / intv
    for i in range(intv):
        yield (start + diff * i).strftime("%Y%m%d")
    yield end.strftime("%Y%m%d")

执行

>>> begin = '20150101'
>>> end = '20150228'
>>> list(date_range(begin, end, 4))
['20150101', '20150115', '20150130', '20150213', '20150228']

原文由 Abhijit 发布,翻译遵循 CC BY-SA 3.0 许可协议

您应该更改日期时间的日期

from datetime import date, datetime, timedelta

begin = '20150101'
end = '20150228'

def get_yyyy_mm_dd(yyyymmdd):
  # given string 'yyyymmdd' return (yyyy, mm, dd)
  year = yyyymmdd[0:4]
  month = yyyymmdd[4:6]
  day = yyyymmdd[6:]
  return int(year), int(month), int(day)

y1, m1, d1 = get_yyyy_mm_dd(begin)
d1 = datetime(y1, m1, d1)
y2, m2, d2 = get_yyyy_mm_dd(end)
d2 = datetime(y2, m2, d2)

def remove_tack(dates_list):
  # given a list of dates in form YYYY-MM-DD return a list of strings in form 'YYYYMMDD'
  tackless = []
  for d in dates_list:
    s = str(d)
    tackless.append(s[0:4]+s[5:7]+s[8:])
  return tackless

def divide_date(date1, date2, intervals):
  dates = [date1]
  delta = (date2-date1).total_seconds()/4
  for i in range(0, intervals):
    dates.append(dates[i] + timedelta(0,delta))
  return remove_tack(dates)

listdates = divide_date(d1, d2, 4)
print listdates

结果:

[‘20150101 00:00:00’, ‘20150115 12:00:00’, ‘20150130 00:00:00’, ‘20150213 12:00:00’, ‘20150228 00:00:00’]

原文由 Jose Ricardo Bustos M. 发布,翻译遵循 CC BY-SA 3.0 许可协议

推荐问题