Как округлить метку времени до ближайшего значения 5 минут - PullRequest
0 голосов
/ 23 марта 2019

У меня есть этот формат для отметки времени:

2019-01-24T00: 00: 05,011719

Как мне округлить это до ближайшего 5-минутного значения? в perl

Редактировать: Хорошо, вопрос довольно расплывчатый и ленивый. Но вопрос остается, просто хочу добавить информацию к моей проблеме.

  1. Я не знаю, что это за формат, поэтому, если я знаю, что могу гуглить, то какая функция или метод конвертирует такие форматы даты.

  2. 20190124000000 Разве это не правильное значение 5 минут? Кстати, я хотел, чтобы он был таким. Но это слишком легко, чтобы быть правильным подходом, это вызывает у меня подозрение, будто я отвечаю на вопросы по математике еще в колледже. В любом случае, я могу просто использовать для этого регулярное выражение.

Ответы [ 2 ]

3 голосов
/ 23 марта 2019
use DateTime::Format::Strptime qw( );

my $format = DateTime::Format::Strptime->new(
    pattern   => '%FT%T.%6N',
    time_zone => 'UTC',       # Or 'local' or 'America/Toronto' or '-0500'
    on_error  => 'croak',
);

my $dt = $format->parse_datetime('2019-01-24T00:00:05.011719');
$dt->set_formatter($format);  # Set default stringification format.

$dt->truncate( to => 'second' )->add( seconds => 1 ) if $dt->nanosecond;
$dt->truncate( to => 'minute' )->add( minutes => 1 ) if $dt->second;
$dt->add( minutes => 5 - ( $dt->minute % 5 ) ) if $dt->minute % 5;

say $dt;  # 2019-01-24T00:05:00.000000

Обратите внимание, что формат, используемый 2019-01-24T00:00:05.011719, является неоднозначным, если соответствующий часовой пояс соблюдает DST (из-за повторяющегося часа в падении).

Кроме того, приведенный выше код корректно обрабатывает разрывы с течением времени, например, возникающие при изменениях летнего времени, если разрыв начинается и заканчивается в точке округления.

1 голос
/ 23 марта 2019

Проблема может быть разбита на:

  • выберите период времени N единицы времени
  • выберите начальную точку (эпоху), где первый (0-й) период времениначинает
  • анализировать отметку времени и преобразовывать ее в "X единицы времени начиная с эпохи"
    • целочисленное деление X на N дает вам номер периода, в котором находится отметка времени
    • остаток от деления X на N дает вам смещение внутри этого периода
    • , если остаток точно равен 0 (ноль), тогда отметка времени находится в началеэтого периода

Ваши требования

  • N - это 5 минут или 300 секунд
  • давайте использовать стандарт UNIX Epoch , т. Е. 1970-01-01T00:00:00Z
  • , который вы хотите округлить до следующего периода, если только отметка времени не является точным началом периода.
  • , поскольку вы этого не сделалиучитывая временную зону, я предполагаю UTC для простоты.

Просто используя основной Perl, то есть Time:: Шт , решение будет:

#!/usr/bin/perl
use warnings;
use strict;

use constant PERIOD => 5 * 60; # 5 minutes

use Time::Piece;

# timezone for Time::Piece->new()
$ENV{TZ} = "UTC";

while (<DATA>) {
    chomp;
    my($iso8601, $fractional) = split(/\./);

    # NOTE: time is interpreted as UTC
    my $t = Time::Piece->strptime($iso8601, '%FT%T');

    # calculate multiple of PERIOD and offset in that period
    my $index  = int($t->epoch / PERIOD);
    my $offset = $t->epoch % PERIOD + "0.${fractional}";

    # round up to next PERIOD unless time is exactly multiple of PERIOD
    $index++ if $offset > 0;

    # convert index back to epoch and generate new Time::Piece object
    # NOTE: timezone offset is set to $ENV{TZ} timezone
    my $t2 = Time::Piece->new($index * PERIOD, 0);

    print "$_ -> ", $t2->strftime('%FT%T'), "\n";
}

exit 0;

__DATA__
2019-01-24T00:00:00.000000
2019-01-24T00:00:05.011719
2019-01-24T00:04:59.999999
2019-01-24T00:05:00.000000
2019-07-24T00:00:00.000000
2019-07-24T00:00:05.011719
2019-07-24T00:04:59.999999
2019-07-24T00:05:00.000000

Тестовый прогон:

$ perl dummy.pl
2019-01-24T00:00:00.000000 -> 2019-01-24T00:00:00
2019-01-24T00:00:05.011719 -> 2019-01-24T00:05:00
2019-01-24T00:04:59.999999 -> 2019-01-24T00:05:00
2019-01-24T00:05:00.000000 -> 2019-01-24T00:05:00
2019-07-24T00:00:00.000000 -> 2019-07-24T00:00:00
2019-07-24T00:00:05.011719 -> 2019-07-24T00:05:00
2019-07-24T00:04:59.999999 -> 2019-07-24T00:05:00
2019-07-24T00:05:00.000000 -> 2019-07-24T00:05:00
...