gpt4 book ai didi

python - 根据一周的标记分区拆分日期时间间隔

转载 作者:行者123 更新时间:2023-12-04 12:02:58 25 4
gpt4 key购买 nike

我有 shift这是一个日期时间间隔(一对 datetime s)。我的周有一个带标签的分区(每周都是一样的:分成几个部分,每个部分都有一个标签)。我要分手shift根据一周的分区划分为标记的部分(即划分为几个子区间)。
例子。 假设 shift是区间 2019-10-21 18:30 - 2019-10-22 08:00 ,一周的分区如下: 周一到周五 07:00 - 19:00 有标签A , 本周剩余时间有标签 B .
在这种情况下shift的 split 应该是以下带标签的子区间列表:

  • 2019-10-21 18:30 - 2019-10-21 19:00带标签A ,
  • 2019-10-21 19:00 - 2019-10-22 07:00带标签B , 和
  • 2019-10-22 07:00 - 2019-10-22 08:00带标签A .

  • 我一般怎么做?
    输入:a datetime间隔(对)和一周的标记分区(如何最好地表示这一点?)
    输出:标记为 datetime 的列表间隔(对)。
    请注意 shift可以在一周内开始并在另一周结束(例如周日晚上到周一早上);每个星期都有相同的标记分区。

    最佳答案

    这是一种获得所需间隔的方法:

    from collections import namedtuple
    from datetime import datetime, timedelta
    import itertools as it


    # Built-in as `it.pairwise` in Python 3.10+
    def pairwise(iterable):
    it = iter(iterable)
    a = next(it, None)
    for b in it:
    yield (a, b)
    a = b


    def beginning_of_week(d: datetime) -> datetime:
    ''' Returns the datetime object for the beginning of the week the provided day is in. '''
    return (d - timedelta(days=d.weekday())).replace(hour=0, minute=0, second=0, microsecond=0)


    Partition = namedtuple('Partition', ('start', 'stop', 'label')) # output format


    def _partition_shift_within_week(start: int, stop: int, partitions):
    ''' Splits the shift (defined by `start` and `stop`) into partitions within one week. '''
    # Get partitions as ranges of absolute offsets from the beginning of the week in seconds
    labels = (x for _, x in partitions)
    absolute_offsets = it.accumulate(int(x.total_seconds()) for x, _ in partitions)
    ranges = [range(x, y) for x, y in pairwise((0, *absolute_offsets))]
    first_part_idx = [start in x for x in ranges].index(True)
    last_part_idx = [stop in x for x in ranges].index(True)
    for r, label in zip((ranges[i] for i in range(first_part_idx, last_part_idx + 1)), labels):
    yield Partition(
    timedelta(seconds=max(r.start, start)), # start of subinterval
    timedelta(seconds=min(r.stop, stop)), # end of the subinterval
    label
    )


    def _partition_shift_unjoined(shift, partitions):
    ''' Partitions a shift across weeks with partitions unjoined at the week edges. '''
    start_monday = beginning_of_week(shift[0])
    stop_monday = beginning_of_week(shift[1])
    seconds_offsets = (
    int((shift[0] - start_monday).total_seconds()),
    *[604800] * ((stop_monday - start_monday).days // 7),
    int((shift[1] - stop_monday).total_seconds()),
    )
    for x, y in pairwise(seconds_offsets):
    num_weeks, x = divmod(x, 604800)
    for part in _partition_shift_within_week(x, y - (y == 604800), partitions):
    weeks_offset = timedelta(weeks=num_weeks)
    yield Partition(
    start_monday + weeks_offset + part.start,
    start_monday + weeks_offset + part.stop,
    part.label
    )


    def partition_shift(shift, partitions):
    ''' Partitions a shift across weeks. '''
    results = []
    for part in _partition_shift_unjoined(shift, partitions):
    if len(results) and results[-1].label == part.label:
    results[-1] = Partition(results[-1].start, part.stop, part.label)
    else:
    results.append(part)
    return results
    用法示例:
    shift = (datetime(2019, 10, 21, 18, 30), datetime(2019, 10, 22, 8, 0))

    # Partitions are stored as successive offsets from the beginning of the week
    partitions = (
    (timedelta(hours=7), 'B'), # Monday morning (midnight to 07:00)
    (timedelta(hours=12), 'A'),
    (timedelta(hours=12), 'B'), # Monday night & Tuesday morning (til 07:00)
    (timedelta(hours=12), 'A'),
    (timedelta(hours=12), 'B'), # Tuesday night & Wednesday morning (til 07:00)
    (timedelta(hours=12), 'A'),
    (timedelta(hours=12), 'B'), # Wednesday night & Thursday morning (til 07:00)
    (timedelta(hours=12), 'A'),
    (timedelta(hours=12), 'B'), # Thursday night & Friday morning (til 07:00)
    (timedelta(hours=12), 'A'),
    (timedelta(hours=53), 'B'), # Friday night & the weekend
    )

    for start, end, label in partition_shift(shift, partitions):
    print(f"'{start}' - '{end}', label: {label}")
    输出:
    '2019-10-21 18:30:00' - '2019-10-21 19:00:00', label: A
    '2019-10-21 19:00:00' - '2019-10-22 07:00:00', label: B
    '2019-10-22 07:00:00' - '2019-10-22 08:00:00', label: A
    这种方法假设分区是作为从那一周开始的连续偏移量输入的。问题没有指定如何提供分区,所以我选择使用这种格式。这很好,因为它保证它们不会重叠,并且使用时间增量而不是固定到某个特定日期。
    将指定分区的其他方式转换为这种方式,或调整此答案以与其他指定分区的方式一起工作,已留给读者作为练习。

    这是另一个用法示例,使用相同的 partitions和以前一样,但是一个 shift从前一周开始,从而证明即使轮类跨越多个星期,这种方法也能奏效。
    shift = (datetime(2019, 10, 19, 18, 30), datetime(2019, 10, 22, 8, 0))

    for start, end, label in partition_shift(shift, partitions):
    print(f"'{start}' - '{end}', label: {label}")
    输出:
    '2019-10-19 18:30:00' - '2019-10-21 07:00:00', label: B
    '2019-10-21 07:00:00' - '2019-10-21 19:00:00', label: A
    '2019-10-21 19:00:00' - '2019-10-22 07:00:00', label: B
    '2019-10-22 07:00:00' - '2019-10-22 08:00:00', label: A

    关于python - 根据一周的标记分区拆分日期时间间隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58579016/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com