将时间范围划分为小时?

问题描述 投票:0回答:1

我目前正在使用包含开始时间,日期和以秒为单位的持续时间的数据集,并且需要能够将从开始时间到(开始时间+持续时间,例如结束时间)的时间范围划分为小时,如果您愿意,则为“时段”。

例如,开始时间为08:30:00,持续时间为9000秒(2.5小时),从8:30:00到09:00:00的小时08持续1800秒,从09到10:00:00 3600秒,依此类推,直到11:00:00的结束时间为止。

什么是最好的方法?我正在使用PHP,但是一般的算法解决方案仍然会非常有用。

我当前的方法如下:

1. Calculate the hour difference between both times (round up to next hour if there's a non-zero number of minutes)
2. Let session progress = 0
3. Iterate the range from 1 to hour difference:
    1. Let the current bucket duration = min(3600, duration)
    2. Let the duration = max(0, duration - current bucket duration)
    3. Let bucket start time = start time + session progress
    4. Let bucket end time = bucket start time + current bucket duration
    5. Do work based on these values
    6. Let session progress += current bucket duration

我的PHP实现如下:

foreach ($csv as $listen_record) {
    $start_dt = $listen_record['Date'] . ' ' . $listen_record['Time'];
    $session_duration = $listen_record['Duration'];

    $session_start_time = date_create_from_format($datetime_format, $start_dt);

    $session_end_time = clone $session_start_time;
    date_add($session_end_time, date_interval_create_from_date_string($session_duration . ' seconds'));

    $diff = date_diff($session_end_time, $session_start_time);
    $hourdiff = $diff->h;

    if ($diff->m > 0)
        $hourdiff += 1;

    $session_progress = 0;

    foreach (range(1, $hourdiff) as $hour) {
        $record_duration = min(3600, $session_duration);
        $session_duration = max(0, $session_duration - $record_duration);

        $record_start_time = clone $session_start_time;
        date_add($record_start_time, date_interval_create_from_date_string($session_progress . ' seconds'));

        $record_end_time = clone $record_start_time;
        date_add($record_end_time, date_interval_create_from_date_string($record_duration . ' seconds'));

        if ($record_start_time == $record_end_time)
            continue;

        // DO WORK...

        $session_progress += $record_duration;
    }
}

[这种将每条记录分成几个小时的时段的工作在某些情况下(尤其是范围跨入新的一天的情况)给出了一些奇怪的结果,并且与实际的挂钟时间不符。

是否有更好的方法可以实际上与挂钟时间保持一致,并且在必须应付午夜的持续时间时却不会惊慌?

谢谢!

php algorithm datetime time
1个回答
0
投票

更新:我设法自己解决了这个问题,所以我发布了我的操作方法,以防万一其他人需要做类似的事情。

基本上,我通过在开始和结束时间戳之间创建一个范围,并过滤掉除开始和结束以外不是3600或3600之前的倍数的每个时间戳,来完成此操作。时间戳记的范围。然后,我可以将数组分成2个块,其中包含插槽的开始时间和结束时间。

我的PHP代码如下,现在可以正常工作:

function is_wall_clock_aligned_hour_boundary($timestamp) {
    return ($timestamp % (60*60) === 0) || (($timestamp + 1) % (60*60) === 0);
}

function create_slot_object($slot) {
    $start_time = reset($slot);
    $end_time = end($slot);
    $duration = $end_time - $start_time;

    return array(
        'startTime' => convert_timestamp_to_datetime($start_time),
        'endTime' => convert_timestamp_to_datetime($end_time),
        'duration' => $duration
    );
}

function make_slots(DateTime $start_time, $duration) {
    $start_timestamp = $start_time->getTimestamp();

    $end_time = clone $start_time;
    date_add($end_time, date_interval_create_from_date_string("$duration seconds"));

    $end_timestamp = $end_time->getTimestamp();

    $time_sequence = range($start_timestamp, $end_timestamp);
    $slot_boundaries = array_filter($time_sequence, 'is_wall_clock_aligned_hour_boundary');

    array_unshift($slot_boundaries, $start_timestamp);
    array_push($slot_boundaries, $end_timestamp);

    $slots = array_chunk($slot_boundaries, 2);

    return array_map('create_slot_object', $slots);
}
© www.soinside.com 2019 - 2024. All rights reserved.