Добавьте время к ISO 8601 раз в Perl

У меня есть время ISO 8601, хранящееся в переменной, и у меня есть некоторое количество часов, хранящихся в другой переменной, например:

my $current_time = shift; #looks like: 2015-07-01T15:38:08Z
my $hours = shift; # looks like: 12

Моя цель - добавить часы к текущему времени, но, похоже, для этого нет встроенной функции Perl. В Powershell вы можете сделать что-то вроде этого:

$currentTime = $currentTime .AddHours($hours)

Есть ли простой способ сделать это в Perl?


person user3270760    schedule 16.12.2015    source источник
comment
$current_time = @_ назначит количество элементов в @_.   -  person choroba    schedule 16.12.2015
comment
верно, но я всегда передаю только одну вещь, а именно текущее_время   -  person user3270760    schedule 16.12.2015
comment
Итак, это эквивалентно $current_time = 1. Используйте shift или my ($current_time).   -  person choroba    schedule 16.12.2015


Ответы (3)


Довольно просто с Time::Piece:

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

use Time::Piece;
use Time::Seconds;

my $current_time = '2015-07-01T15:38:08Z';
my $hours = 12;

my $format = '%Y-%m-%dT%H:%M:%SZ';
my $time = 'Time::Piece'->strptime($current_time, $format);
$time += $hours * ONE_HOUR;

print $time->strftime($format), "\n";
person choroba    schedule 16.12.2015
comment
Это красиво добавило часы, но преобразовало формат в Wed Jul 1 15:38:08 2015 Есть ли способ сохранить формат ISO 8061? - person user3270760; 16.12.2015
comment
@ user3270760: см. метод strftime. - person choroba; 16.12.2015
comment
Понятно: $new_time = $new_time -> strftime('%Y-%m-%dT%H:%M:%SZ');' на случай, если возникнет интерес в будущем. Спасибо! - person user3270760; 16.12.2015
comment
$time->datetime также предоставит вам формат ISO 8601. - person Matt Jacob; 16.12.2015
comment
@Matt Jacob, здесь используется профиль ISO 8601, отличный от входного (YYYY-MM-DDThh:mm:ss вместо YYYY-MM-DDThh:mm:ssZ). Вам понадобится $time->datetime . 'Z'. - person ikegami; 16.12.2015
comment
Так что добавьте Z в конец! Кажется проще, чем указывать всю строку формата. (Или просто сохраните строку формата в переменной, поскольку она одинакова для ввода и вывода.) - person Matt Jacob; 16.12.2015

Этот конкретный профиль ISO 8601 также известен как RFC3339.

use DateTime::Format::RFC3339;

my $dt = DateTime::Format::RFC3339->parse_datetime('2015-07-01T15:38:08Z');
$dt->add( hours => 1 );
print "$dt\n";  # 2015-07-01T16:38:08Z

Если вы хотите принимать произвольные профили ISO 8601, вы можете использовать DateTime::Format::ISO8601.

use DateTime::Format::ISO8601;

my $dt = DateTime::Format::ISO8601->parse_datetime('2015-07-01T15:38:08Z');
$dt->set_time_zone('UTC');  # Convert to UTC ("Z") if it's not already.
$dt->add( hours => 1 );
print $dt->iso8601().'Z', "\n";  # 2015-07-01T16:38:08Z

Я разместил эти альтернативы, потому что эти модули гораздо менее подвержены ошибкам, чем Time::Piece.

person ikegami    schedule 16.12.2015

Вы также можете использовать Time::Moment. В интересах полного раскрытия информации я являюсь автором Time::Moment.

say Time::Moment->from_string('2015-07-01T15:38:08Z')
                ->plus_hours(1);

Выход:

2015-07-01T16:38:08Z
person chansen    schedule 16.12.2015