Как преобразовать дату / время в время эпохи (Unix время / секунды с 1970 года) в Perl? - PullRequest
41 голосов
/ 18 сентября 2008

Учитывая дату / время в виде массива (год, месяц, день, час, минута, секунда), как бы вы преобразовали его в время эпохи, то есть количество секунд с 1970-01-01 00:00 : 00 GMT?

Бонусный вопрос: Если бы вы дали дату / время в виде строки, как бы вы сначала проанализировали ее в массиве (y, m, d, h, m, s)?

Ответы [ 12 ]

34 голосов
/ 18 сентября 2008

Если вы используете модуль DateTime , вы можете вызвать метод epoch () для объекта DateTime, поскольку это то, что вы считаете временем unix.

Использование DateTimes позволяет довольно легко конвертировать из эпох в объекты даты.

Альтернативно, localtime и gmtime преобразуют эпоху в массив, содержащий день месяц и год, а timelocal и timegm из модуля Time :: Local сделают обратное, преобразовав массив временных элементов (секунд, минут, ..., дней, месяцев и т. д.) в эпоху.

19 голосов
/ 18 сентября 2008

Это самый простой способ получить время Unix:

use Time::Local;
timelocal($second,$minute,$hour,$day,$month-1,$year);

Обратите внимание на обратный порядок аргументов, и что январь - месяц 0. Дополнительные параметры см. В модуле DateTime из CPAN.

Что касается синтаксического анализа, см. Модуль Date :: Parse из CPAN. Если вам действительно нужно разбираться с парсингом дат, Date :: Manip может быть полезен, хотя его собственная документация предупреждает вас об этом, поскольку он несет много багажа (он знает такие вещи, как обычные деловые каникулы). например) и другие решения гораздо быстрее.

Если вам что-то известно о формате даты / времени, которое вы будете анализировать, тогда может быть достаточно простого регулярного выражения, но вам, вероятно, лучше использовать соответствующий модуль CPAN. Например, если вы знаете, что даты всегда будут в порядке YMDHMS, используйте модуль CPAN DateTime :: Format :: ISO8601 .


Для справки, если не сказать ничего другого, ниже приведена функция, которую я использую для приложения, в котором, как я знаю, даты всегда будут в порядке YMDHMS, причем часть или часть HMS необязательна. Он принимает любые разделители (например, «2009-02-15» или «2009.02.15»). Он возвращает соответствующее время Unix (в секундах с 1970-01-01 00:00:00 по Гринвичу) или -1, если он не может его проанализировать (что означает, что вам лучше быть уверенным, что вам никогда не понадобится законно анализировать дату 1969- 12-31 23:59:59). Это также предполагает двузначные годы XX до «69», относящиеся к «20XX», в противном случае «19XX» (например, «50-02-15» означает 2050-02-15, но «75-02-15» означает 1975- 02-15).

use Time::Local;

sub parsedate { 
  my($s) = @_;
  my($year, $month, $day, $hour, $minute, $second);

  if($s =~ m{^\s*(\d{1,4})\W*0*(\d{1,2})\W*0*(\d{1,2})\W*0*
                 (\d{0,2})\W*0*(\d{0,2})\W*0*(\d{0,2})}x) {
    $year = $1;  $month = $2;   $day = $3;
    $hour = $4;  $minute = $5;  $second = $6;
    $hour |= 0;  $minute |= 0;  $second |= 0;  # defaults.
    $year = ($year<100 ? ($year<70 ? 2000+$year : 1900+$year) : $year);
    return timelocal($second,$minute,$hour,$day,$month-1,$year);  
  }
  return -1;
}
17 голосов
/ 18 сентября 2008

Чтобы проанализировать дату, посмотрите на Date :: Parse в CPAN.

7 голосов
/ 12 февраля 2015

Я знаю, что это старый вопрос, но подумал, что предложу другой ответ.

Time::Piece является ядром на Perl 5.9.5

Это позволяет анализировать время в произвольных форматах с помощью метода strptime.

например:.

my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
                              "%A %drd %b, %Y");

Полезная часть - поскольку это перегруженный объект, вы можете использовать его для числовых сравнений.

например.

if ( $t < time() ) { #do something }

Или если вы обращаетесь к нему в строковом контексте:

print $t,"\n"; 

Вы получаете:

Wed Nov  3 00:00:00 1943

Существует множество методов доступа, которые допускают некоторые другие полезные преобразования, основанные на времени. https://metacpan.org/pod/Time::Piece

7 голосов
/ 24 сентября 2008
$ENV{TZ}="GMT";
POSIX::tzset();
$time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900);
6 голосов
/ 18 сентября 2008

Get Date :: Manip from CPAN , затем:

use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );

редактирование:

Date :: Manip большой и медленный, но очень гибкий в разборе и чистый perl. Используйте его, если вы спешите, когда пишете код, и вы знаете, что не будете спешить, когда запускаете его.

например. Используйте его для разбора параметров командной строки при запуске, но не используйте его для анализа больших объемов данных на занятом веб-сервере.

См. комментарии авторов .

(Спасибо автору первого комментария ниже)

2 голосов
/ 23 марта 2010

Для дальнейшего использования, один вкладыш, который может быть применен, например, в скриптах !#/bin/sh.

EPOCH="`perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`"

Только не забывайте избегать восьмеричных значений!

2 голосов
/ 19 сентября 2008

В CPAN существует множество модулей манипулирования датой. Особенно мне нравится DateTime , и вы можете использовать strptime modules для разбора дат в произвольных форматах. Существует также много модулей DateTime :: Format в CPAN для обработки специализированных форматов даты, но strptime является наиболее общим.

2 голосов
/ 19 сентября 2008

Возможно, один из лучших примеров «Есть больше, чем один способ сделать это», с помощью или без помощи CPAN.

Если у вас есть контроль над тем, что вы передаете как «дата / время», я бы предложил пойти по маршруту DateTime либо с использованием определенного подкласса Date :: Time :: Format, либо используя DateTime :: Format :: Strptime, если не существует ни одного, поддерживающего ваш дурацкий формат даты (см. FAQ по дате и времени для получения дополнительной информации). В общем, Date :: Time - это то, что нужно, если вы хотите сделать что-то серьезное с результатом: лишь немногие классы по CPAN настолько анально-сохраняемы и одержимо точны.

Если вы ожидаете странных вещей в произвольной форме, бросьте их в Date :: Parse * метод str2time () , который даст вам значение секунды с начала эпохи, которое вы можете использовать для злого кстати, без накладных расходов Date :: Manip .

2 голосов
/ 18 сентября 2008

Мой любимый синтаксический анализатор даты и времени - DateTime :: Format :: ISO8601 Как только вы это заработаете, у вас будет объект DateTime, который легко конвертируется в секунды эпох с помощью epoch ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...