perl, int номер секунды с 1970 года
Используя старый выпуск программного обеспечения EPrints, у меня есть эта функция EPrints::Time::datestring_to_timet, чтобы возвращать целое число секунд с 1970 года
######################################################################
=pod
=item $xhtml = EPrints::Time::datestring_to_timet( $handle, $datevalue )
Returns an interger number of seconds since 1970-01-01:00:00
$datevalue - in the format YYYY-MM-DDTHH:MM:SSZ
=cut
######################################################################
sub datestring_to_timet
{
my( $session, $datevalue, $short ) = @_;
my( $year,$mon,$day,$hour,$min,$sec ) = split /[- :TZ]/, $datevalue;
my $t = timegm_nocheck $sec||0,$min||0,$hour,$day,$mon-1,$year-1900;
return $t;
}
если использовать с годом в далеком будущем, я получил отрицательное число:
print EPrints::Time::datestring_to_timet(undef, "3017-9-20T12:00:00Z");
результат:
-26895412800
что здесь не так?
1 ответ
Я думаю, что этот пакет использует 32-разрядное целое число для представления секунд. Это ошибка, потому что она приводит к так называемой проблеме 2038 года - 19 января 2038 года число секунд с 1 января 1970 года достигает 231, и происходит целочисленное переполнение.
На самом деле, поскольку вы пытаетесь использовать год 3017, это переполнение происходит много раз (через каждые 68 лет).
Типичным решением этой проблемы является использование 64-битных чисел в течение нескольких секунд.
Другая возможность заключается в том, что вы используете старый 32-битный Perl. Обновление до 64-битного Perl (вместе с вашим пакетом) может исправить это само по себе.
В качестве альтернативы вы можете использовать пакет DateTime. Он поддерживает достаточно большие временные метки даже на 32-битном Perl, используя числа с плавающей запятой (53 бита).
$ perl -V:ivsize
ivsize='4';
$ perl -MDateTime::Format::RFC3339 -E'
say DateTime::Format::RFC3339
->parse_datetime("3017-09-20T12:00:00Z")
->epoch'
33062817600