perl strftime локальное время минус 12 часов

Я использую perl strftime для (сейчас datetime)

perl -MPOSIX -e 'print POSIX::strftime("%m/%d/%Y %H:%M", localtime());'

я хочу минус datetime сейчас на 12 часов

Пример OUTPUT: от 2/7/2020 1:00 до 2/6/2020 13:00 ‹- минус 12 часов только

Пожалуйста, помогите решить эту проблему, используя указанный код


person Drin    schedule 07.02.2020    source источник


Ответы (2)


POSIX strftime

Возвращает строку.

и вы не можете удобно вычитать часы из строки.

Вместо этого используйте библиотеку для обработки даты и времени для манипуляций, а затем отформатируйте с помощью strftime

Пример с Time::Piece

perl -MTime::Piece -MTime::Seconds -wE'
    $t = (localtime) - 12*ONE_HOUR;
    say $t->strftime("%m/%d/%Y %H:%M")'

Time::Seconds поставляется вместе с Time::Piece для различных вычислений даты и времени.

В то время как Time::Piece является основным, хорошим и хорошо известным, у него есть тонкости и ограничения, и для более сложной работы я бы рекомендовал всезнающий (и большой и тяжелый) ДатаВремя

perl -MDateTime -wE'
    $t = DateTime->now(time_zone => "local")->subtract(hours => 12); 
    say $t->strftime("%m/%d/%Y %H:%M")'

Я думаю, стоит подчеркнуть, что этот модуль может делать практически все с datetime.


В качестве примечания имейте в виду проблемы, связанные с переходом на летнее время. Между чудесными скачками часов и случайными несуществующими часами могут быть неприятные сюрпризы, хотя и редко (пример).

Вот программа, предоставленная ikegami для проверки перехода на летнее время (08 марта, 2:00 -> 3:00)

use strict;
use warnings;

use DateTime      qw( );
use POSIX         qw( strftime );
use Time::Piece   qw( localtime );
use Time::Seconds qw( ONE_HOUR );

my $epoch = 1583683200;  # 2020-03-08T12:00:00

CORE::say
   for
      DateTime->from_epoch( epoch => $epoch, time_zone => $ENV{TZ} )
              ->subtract( hours => 12 ),
      strftime("%FT%T", localtime($epoch - 12*60*60)),
      ( localtime($epoch) - 12*ONE_HOUR )->strftime("%FT%T");

Затем установите переменную среды TZ и запустите ее.

TZ=America/New_York perl test_DST.pl

(в bash, а в tcsh это setenv TZ "America/New_York"; perl test_DST.pl)

Выход

2020-03-07T23:00:00
2020-03-07T23:00:00
2020-03-07T23:00:00

Функция с таким именем существует во многих средах и всегда возвращает отформатированную строку.

person zdim    schedule 07.02.2020
comment
@ikegami А, отлично! Интересно, что все (три метода, показанные на этой странице — localtime настройка и два в этом ответе) работают одинаково. Я не понимаю, однако, как он заканчивается (скорее вниз) в 23:00 ... (я думаю, было бы неплохо включить этот ваш код в этот ответ) - person zdim; 07.02.2020
comment
America/New_York использует EDT для начального ts, но EST для более раннего ts. 12 часов до полудня по восточному поясному времени — это полночь по восточному поясному времени или 23:00 по восточному поясному времени. - person ikegami; 07.02.2020
comment
@ikegami тьфу, верно. Спасибо. я добавил вашу программу в пост - person zdim; 07.02.2020

Использование Time::Moment и Time::Moment::Role::TimeZone (для исправления изменений летнего времени):

perl -MTime::Moment -MWith::Roles -E'say Time::Moment->with::roles("+TimeZone")->now
  ->minus_hours(12)->with_system_offset_same_instant->strftime("%m/%d/%Y %H:%M")'
person Grinnz    schedule 07.02.2020