如何在 python 中将一个时段分解为一组子时段(小时、刻钟和分钟)

how to decompose a period into a set of subperiods (hour, quarter-hour and minute) in python

我想将一个周期分成几个预定义大小的子周期。

这是一个例子:

在 2021-04-11 15:03:00 和 2021-04-11 18:03:00 之间,分解为小时、刻钟和分钟。预期结果是(无具体顺序):

2021-04-11 15:03:00 (the minute)
2021-04-11 15:04:00 (the minute)
2021-04-11 15:05:00 (the minute)
2021-04-11 15:06:00 (the minute)
2021-04-11 15:07:00 (the minute)
2021-04-11 15:08:00 (the minute)
2021-04-11 15:09:00 (the minute)
2021-04-11 15:10:00 (the minute)
2021-04-11 15:11:00 (the minute)
2021-04-11 15:12:00 (the minute)
2021-04-11 15:13:00 (the minute)
2021-04-11 15:14:00 (the minute)
2021-04-11 15:15:00 (the quarter-hour)
2021-04-11 15:30:00 (the quarter-hour)
2021-04-11 15:45:00 (the quarter-hour)
2021-04-11 16:00:00 (the hour)
2021-04-11 17:00:00 (the hour)
2021-04-11 18:00:00 (the minute)
2021-04-11 18:01:00 (the minute)
2021-04-11 18:02:00 (the minute)

我当前的代码:

def ceil_dt(dt, delta):
    return dt + (datetime.min - dt) % delta

def floor_dt(dt, delta):
    return dt - (dt - datetime.min) % delta

def list_dt(start, end, subperiod, indice):
    temp = start
    min = ceil_dt(temp, timedelta(minutes=subperiod[indice]))

    print(f'\nstart {start}')
    print(f'end {end}')
    print(f'subperiod {subperiod}')
    print(f'indice {indice}')
    print(f'min {min}')

    while temp + timedelta(minutes=subperiod[indice]) <= floor_dt(end, timedelta(minutes=subperiod[indice])) :
        print(f'result {ceil_dt(temp, timedelta(minutes=subperiod[indice]))}')
        temp = temp + timedelta(minutes=subperiod[indice])
        max = ceil_dt(temp, timedelta(minutes=subperiod[indice]))

    print(f'max {max}')

    if min != start:
        print("other min")
        indice = indice + 1
        list_dt(start, min, subperiod, indice)

#     if max != end:
#         print("other max")
#         indice = indice + 1
#         list_dt(max, end, subperiod, indice)


subperiod = [60, 15, 1]
indice = 0

start = datetime(2021, 4, 11, 15, 3, 0)
end = datetime(2021, 4, 11, 18, 3, 0)
list_dt(start, end, subperiod, indice)

我找不到如何正确输入最小值和最大值部分。 我不确定我们是否应该使用递归。有人有想法吗?

您可以使用 while 循环:

from datetime import datetime, timedelta as td
def list_dt(d1, d2):
  while d1 < d2:
     yield d1
     if not d1.minute and d1+td(hours = 1) <= d2:
        d1 += td(hours = 1)
     elif not d1.minute%15 and d1+td(minutes = 15) <= d2:
        d1 += td(minutes = 15)
     else:
        d1 += td(minutes = 1)

for a, b in [[datetime(2021, 4, 11, 15, 3, 0), datetime(2021, 4, 11, 18, 3, 0)], [datetime(2021, 4, 11, 15, 0, 0), datetime(2021, 4, 11, 18, 0, 0)], [datetime(2021, 4, 11, 15, 15, 0), datetime(2021, 4, 11, 18, 30, 0)]]:
   for i in list_dt(a, b):
      print(str(i))
   print('-'*20)

输出:

2021-04-11 15:03:00
2021-04-11 15:04:00
2021-04-11 15:05:00
2021-04-11 15:06:00
2021-04-11 15:07:00
2021-04-11 15:08:00
2021-04-11 15:09:00
2021-04-11 15:10:00
2021-04-11 15:11:00
2021-04-11 15:12:00
2021-04-11 15:13:00
2021-04-11 15:14:00
2021-04-11 15:15:00
2021-04-11 15:30:00
2021-04-11 15:45:00
2021-04-11 16:00:00
2021-04-11 17:00:00
2021-04-11 18:00:00
2021-04-11 18:01:00
2021-04-11 18:02:00
--------------------
2021-04-11 15:00:00
2021-04-11 16:00:00
2021-04-11 17:00:00
--------------------
2021-04-11 15:15:00
2021-04-11 15:30:00
2021-04-11 15:45:00
2021-04-11 16:00:00
2021-04-11 17:00:00
2021-04-11 18:00:00
2021-04-11 18:15:00
--------------------

您所描述的内容已通过 datetime 的 rrule 提供。作为一个基本示例,您可以像这样编写一个函数:

    import dateutil.rrule as rrule
    from datetime import datetime, timedelta
    
    # function to round to nearest n time
    def round_nearest(date, **kwargs):
        secs = timedelta(**kwargs).total_seconds()
        return datetime.fromtimestamp(date.timestamp() + secs - date.timestamp() % secs)
    
    # function to return per OP's post
    def hours_aligned(start, end, inc = True):
        print("Minutes")
        if inc: yield start # remove if you don't require start
        rule = rrule.rrule(rrule.MINUTELY, dtstart=start)
        for x in rule.between(start, end, inc = False):
            yield x
        if inc: yield end # remove if you don't require end
    
        print("Hours")
        if inc: yield start # remove if you don't require start
        rule = rrule.rrule(rrule.HOURLY, dtstart=start)
        for x in rule.between(start, end, inc = False):
            yield x
        if inc: yield end # remove if you don't require end
    
        print("Quarter Hours")
        if inc: yield start # remove if you don't require start
        rule = rrule.rrule(rrule.MINUTELY, interval=15, dtstart=round_nearest(start, minutes=15))
        for x in rule.between(start, end, inc = False):
            yield x
        if inc: yield end # remove if you don't require end
    
    
    start = datetime(2021, 4, 11, 15, 3, 0)
    end = datetime(2021, 4, 11, 18, 3, 0)
    
    for x in hours_aligned(start, end, inc=True):
        print(x)

Minutes
2021-04-11 15:03:00
2021-04-11 15:04:00
2021-04-11 15:05:00
2021-04-11 15:06:00
2021-04-11 15:07:00
2021-04-11 15:08:00
2021-04-11 15:09:00
2021-04-11 15:10:00
2021-04-11 15:11:00
2021-04-11 15:12:00
2021-04-11 15:13:00
2021-04-11 15:14:00
2021-04-11 15:15:00
2021-04-11 15:16:00
2021-04-11 15:17:00
2021-04-11 15:18:00
2021-04-11 15:19:00
2021-04-11 15:20:00
2021-04-11 15:21:00
2021-04-11 15:22:00
2021-04-11 15:23:00
2021-04-11 15:24:00
2021-04-11 15:25:00
2021-04-11 15:26:00
2021-04-11 15:27:00
2021-04-11 15:28:00
2021-04-11 15:29:00
2021-04-11 15:30:00
2021-04-11 15:31:00
2021-04-11 15:32:00
2021-04-11 15:33:00
2021-04-11 15:34:00
2021-04-11 15:35:00
2021-04-11 15:36:00
2021-04-11 15:37:00
2021-04-11 15:38:00
2021-04-11 15:39:00
2021-04-11 15:40:00
2021-04-11 15:41:00
2021-04-11 15:42:00
2021-04-11 15:43:00
2021-04-11 15:44:00
2021-04-11 15:45:00
2021-04-11 15:46:00
2021-04-11 15:47:00
2021-04-11 15:48:00
2021-04-11 15:49:00
2021-04-11 15:50:00
2021-04-11 15:51:00
2021-04-11 15:52:00
2021-04-11 15:53:00
2021-04-11 15:54:00
2021-04-11 15:55:00
2021-04-11 15:56:00
2021-04-11 15:57:00
2021-04-11 15:58:00
2021-04-11 15:59:00
2021-04-11 16:00:00
2021-04-11 16:01:00
2021-04-11 16:02:00
2021-04-11 16:03:00
2021-04-11 16:04:00
2021-04-11 16:05:00
2021-04-11 16:06:00
2021-04-11 16:07:00
2021-04-11 16:08:00
2021-04-11 16:09:00
2021-04-11 16:10:00
2021-04-11 16:11:00
2021-04-11 16:12:00
2021-04-11 16:13:00
2021-04-11 16:14:00
2021-04-11 16:15:00
2021-04-11 16:16:00
2021-04-11 16:17:00
2021-04-11 16:18:00
2021-04-11 16:19:00
2021-04-11 16:20:00
2021-04-11 16:21:00
2021-04-11 16:22:00
2021-04-11 16:23:00
2021-04-11 16:24:00
2021-04-11 16:25:00
2021-04-11 16:26:00
2021-04-11 16:27:00
2021-04-11 16:28:00
2021-04-11 16:29:00
2021-04-11 16:30:00
2021-04-11 16:31:00
2021-04-11 16:32:00
2021-04-11 16:33:00
2021-04-11 16:34:00
2021-04-11 16:35:00
2021-04-11 16:36:00
2021-04-11 16:37:00
2021-04-11 16:38:00
2021-04-11 16:39:00
2021-04-11 16:40:00
2021-04-11 16:41:00
2021-04-11 16:42:00
2021-04-11 16:43:00
2021-04-11 16:44:00
2021-04-11 16:45:00
2021-04-11 16:46:00
2021-04-11 16:47:00
2021-04-11 16:48:00
2021-04-11 16:49:00
2021-04-11 16:50:00
2021-04-11 16:51:00
2021-04-11 16:52:00
2021-04-11 16:53:00
2021-04-11 16:54:00
2021-04-11 16:55:00
2021-04-11 16:56:00
2021-04-11 16:57:00
2021-04-11 16:58:00
2021-04-11 16:59:00
2021-04-11 17:00:00
2021-04-11 17:01:00
2021-04-11 17:02:00
2021-04-11 17:03:00
2021-04-11 17:04:00
2021-04-11 17:05:00
2021-04-11 17:06:00
2021-04-11 17:07:00
2021-04-11 17:08:00
2021-04-11 17:09:00
2021-04-11 17:10:00
2021-04-11 17:11:00
2021-04-11 17:12:00
2021-04-11 17:13:00
2021-04-11 17:14:00
2021-04-11 17:15:00
2021-04-11 17:16:00
2021-04-11 17:17:00
2021-04-11 17:18:00
2021-04-11 17:19:00
2021-04-11 17:20:00
2021-04-11 17:21:00
2021-04-11 17:22:00
2021-04-11 17:23:00
2021-04-11 17:24:00
2021-04-11 17:25:00
2021-04-11 17:26:00
2021-04-11 17:27:00
2021-04-11 17:28:00
2021-04-11 17:29:00
2021-04-11 17:30:00
2021-04-11 17:31:00
2021-04-11 17:32:00
2021-04-11 17:33:00
2021-04-11 17:34:00
2021-04-11 17:35:00
2021-04-11 17:36:00
2021-04-11 17:37:00
2021-04-11 17:38:00
2021-04-11 17:39:00
2021-04-11 17:40:00
2021-04-11 17:41:00
2021-04-11 17:42:00
2021-04-11 17:43:00
2021-04-11 17:44:00
2021-04-11 17:45:00
2021-04-11 17:46:00
2021-04-11 17:47:00
2021-04-11 17:48:00
2021-04-11 17:49:00
2021-04-11 17:50:00
2021-04-11 17:51:00
2021-04-11 17:52:00
2021-04-11 17:53:00
2021-04-11 17:54:00
2021-04-11 17:55:00
2021-04-11 17:56:00
2021-04-11 17:57:00
2021-04-11 17:58:00
2021-04-11 17:59:00
2021-04-11 18:00:00
2021-04-11 18:01:00
2021-04-11 18:02:00
2021-04-11 18:03:00
Hours
2021-04-11 15:03:00
2021-04-11 16:03:00
2021-04-11 17:03:00
2021-04-11 18:03:00
Quarter Hours
2021-04-11 15:03:00
2021-04-11 15:15:00
2021-04-11 15:30:00
2021-04-11 15:45:00
2021-04-11 16:00:00
2021-04-11 16:15:00
2021-04-11 16:30:00
2021-04-11 16:45:00
2021-04-11 17:00:00
2021-04-11 17:15:00
2021-04-11 17:30:00
2021-04-11 17:45:00
2021-04-11 18:00:00
2021-04-11 18:03:00

我创建了 3 条规则,按分钟(即 MINUTELY)、按分钟但间隔 15 分钟,然后按小时(即 HOURLY)。 Inc 只是您是否要包括开始结束。