大纪元时间到日期和时间的完全手动转换
Full manual conversion of Epoch time to Date and Time
我编写了这个 Perl 脚本来将文件中的日期和时间转换为纪元时间。
原来的日期格式是dd-mm-yyyy hh:MM:ss
我这样做的原因是因为我必须将这些值写入数据库并且列只接受整数值。
use strict;
use warnings;
use Time::Local;
$datestring = '07-06-2019 21:13:00';
my ($dd, $mm, $yyyy, $hh, $min, $sec) = split /\W+/, $datestring;
my $epoch = timelocal($sec,$min,$hh,$dd,$mm-1,$yyyy-1900);
print("$epoch\n");
将日期 07-06-2019 21:13:00
转换为 1559934780
问题:
这些值现在显示在用户无法读取的前端中,前端没有脚本实用程序,我只能使用许多不同的计算公式来使其可读。
是否有完全手动的方法,只需使用 calculator/calculation 将纪元时间转换回用户可读的日期和时间?
核心 Time::Piece 可以根据您当地的时区进行双向转换。
use strict;
use warnings;
use Time::Piece;
my $datestring = '07-06-2019 21:13:00';
my $time = localtime->strptime($datestring, '%d-%m-%Y %H:%M:%S');
my $epoch = $time->epoch;
...
my $time = localtime($epoch);
my $datestring = $time->strftime('%d-%m-%Y %H:%M:%S');
查看任何标准的 strftime 或 strptime 手册页,了解通常被接受的格式说明符 - 不幸的是,Time::Piece 接受的那些没有记录。
无法访问自 Perl 5.10 以来的核心 Time::Piece,您可以使用内置的 localtime 函数,它只是有点复杂(如 timelocal)。
use strict;
use warnings;
my $epoch = 1559934780;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime $epoch;
my $date_string = sprintf '%02d-%02d-%04d %02d:%02d:%02d',
$mday, $mon+1, $year+1900, $hour, $min, $sec;
在 DateTime.pm 的早期版本中,您会发现一个子 _rd2greg,我将其编写为 jd2greg,用于 Rich Bowen 早期且长期停产的 Reefknot 项目。这需要从第一年开始算起的天数,并产生年、月和日。您可以将纪元时间除以 86400(一天中的秒数)并加上 719163(截至 1970 年的天数)以传递给它。
这里jd2greg和对应的greg2jd:
=head2 jd2greg
($year, $month, $day) = jd2greg( $jd );
Convert number of days on or after Jan 1, 1 CE (Gregorian) to
gregorian year,month,day.
=cut
sub jd2greg {
use integer;
my $d = shift;
my $yadj = 0;
my ( $c, $y, $m );
# add 306 days to make relative to Mar 1, 0; also adjust $d to be within
# a range (1..2**28-1) where our calculations will work with 32bit ints
if ( $d > 2**28 - 307 ) {
# avoid overflow if $d close to maxint
$yadj = ( $d - 146097 + 306 ) / 146097 + 1;
$d -= $yadj * 146097 - 306;
} elsif ( ( $d += 306 ) <= 0 )
{
$yadj =
-( -$d / 146097 + 1 ); # avoid ambiguity in C division of negatives
$d -= $yadj * 146097;
}
$c =
( $d * 4 - 1 ) / 146097; # calc # of centuries $d is after 29 Feb of yr 0
$d -= $c * 146097 / 4; # (4 centuries = 146097 days)
$y = ( $d * 4 - 1 ) / 1461; # calc number of years into the century,
$d -= $y * 1461 / 4; # again March-based (4 yrs =~ 146[01] days)
$m =
( $d * 12 + 1093 ) / 367; # get the month (3..14 represent March through
$d -= ( $m * 367 - 1094 ) / 12; # February of following year)
$y += $c * 100 + $yadj * 400; # get the real year, which is off by
++$y, $m -= 12 if $m > 12; # one if month is January or February
return ( $y, $m, $d );
}
=head2 greg2jd
$jd = greg2jd( $year, $month, $day );
Convert gregorian year,month,day to days on or after Jan 1, 1 CE
(Gregorian). Normalization is performed (e.g. month of 28 means
April two years after given year) for month < 1 or > 12 or day < 1
or > last day of month.
=cut
sub greg2jd {
use integer;
my ( $y, $m, $d ) = @_;
my $adj;
# make month in range 3..14 (treat Jan & Feb as months 13..14 of prev year)
if ( $m <= 2 ) {
$y -= ( $adj = ( 14 - $m ) / 12 );
$m += 12 * $adj;
} elsif ( $m > 14 )
{
$y += ( $adj = ( $m - 3 ) / 12 );
$m -= 12 * $adj;
}
# make year positive (oh, for a use integer 'sane_div'!)
if ( $y < 0 ) {
$d -= 146097 * ( $adj = ( 399 - $y ) / 400 );
$y += 400 * $adj;
}
# add: day of month, days of previous 0-11 month period that began w/March,
# days of previous 0-399 year period that began w/March of a 400-multiple
# year), days of any 400-year periods before that, and 306 days to adjust
# from Mar 1, year 0-relative to Jan 1, year 1-relative (whew)
$d += ( $m * 367 - 1094 ) / 12 + $y % 100 * 1461 / 4 +
( $y / 100 * 36524 + $y / 400 ) - 306;
}
我编写了这个 Perl 脚本来将文件中的日期和时间转换为纪元时间。
原来的日期格式是dd-mm-yyyy hh:MM:ss
我这样做的原因是因为我必须将这些值写入数据库并且列只接受整数值。
use strict;
use warnings;
use Time::Local;
$datestring = '07-06-2019 21:13:00';
my ($dd, $mm, $yyyy, $hh, $min, $sec) = split /\W+/, $datestring;
my $epoch = timelocal($sec,$min,$hh,$dd,$mm-1,$yyyy-1900);
print("$epoch\n");
将日期 07-06-2019 21:13:00
转换为 1559934780
问题: 这些值现在显示在用户无法读取的前端中,前端没有脚本实用程序,我只能使用许多不同的计算公式来使其可读。
是否有完全手动的方法,只需使用 calculator/calculation 将纪元时间转换回用户可读的日期和时间?
核心 Time::Piece 可以根据您当地的时区进行双向转换。
use strict;
use warnings;
use Time::Piece;
my $datestring = '07-06-2019 21:13:00';
my $time = localtime->strptime($datestring, '%d-%m-%Y %H:%M:%S');
my $epoch = $time->epoch;
...
my $time = localtime($epoch);
my $datestring = $time->strftime('%d-%m-%Y %H:%M:%S');
查看任何标准的 strftime 或 strptime 手册页,了解通常被接受的格式说明符 - 不幸的是,Time::Piece 接受的那些没有记录。
无法访问自 Perl 5.10 以来的核心 Time::Piece,您可以使用内置的 localtime 函数,它只是有点复杂(如 timelocal)。
use strict;
use warnings;
my $epoch = 1559934780;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime $epoch;
my $date_string = sprintf '%02d-%02d-%04d %02d:%02d:%02d',
$mday, $mon+1, $year+1900, $hour, $min, $sec;
在 DateTime.pm 的早期版本中,您会发现一个子 _rd2greg,我将其编写为 jd2greg,用于 Rich Bowen 早期且长期停产的 Reefknot 项目。这需要从第一年开始算起的天数,并产生年、月和日。您可以将纪元时间除以 86400(一天中的秒数)并加上 719163(截至 1970 年的天数)以传递给它。
这里jd2greg和对应的greg2jd:
=head2 jd2greg
($year, $month, $day) = jd2greg( $jd );
Convert number of days on or after Jan 1, 1 CE (Gregorian) to
gregorian year,month,day.
=cut
sub jd2greg {
use integer;
my $d = shift;
my $yadj = 0;
my ( $c, $y, $m );
# add 306 days to make relative to Mar 1, 0; also adjust $d to be within
# a range (1..2**28-1) where our calculations will work with 32bit ints
if ( $d > 2**28 - 307 ) {
# avoid overflow if $d close to maxint
$yadj = ( $d - 146097 + 306 ) / 146097 + 1;
$d -= $yadj * 146097 - 306;
} elsif ( ( $d += 306 ) <= 0 )
{
$yadj =
-( -$d / 146097 + 1 ); # avoid ambiguity in C division of negatives
$d -= $yadj * 146097;
}
$c =
( $d * 4 - 1 ) / 146097; # calc # of centuries $d is after 29 Feb of yr 0
$d -= $c * 146097 / 4; # (4 centuries = 146097 days)
$y = ( $d * 4 - 1 ) / 1461; # calc number of years into the century,
$d -= $y * 1461 / 4; # again March-based (4 yrs =~ 146[01] days)
$m =
( $d * 12 + 1093 ) / 367; # get the month (3..14 represent March through
$d -= ( $m * 367 - 1094 ) / 12; # February of following year)
$y += $c * 100 + $yadj * 400; # get the real year, which is off by
++$y, $m -= 12 if $m > 12; # one if month is January or February
return ( $y, $m, $d );
}
=head2 greg2jd
$jd = greg2jd( $year, $month, $day );
Convert gregorian year,month,day to days on or after Jan 1, 1 CE
(Gregorian). Normalization is performed (e.g. month of 28 means
April two years after given year) for month < 1 or > 12 or day < 1
or > last day of month.
=cut
sub greg2jd {
use integer;
my ( $y, $m, $d ) = @_;
my $adj;
# make month in range 3..14 (treat Jan & Feb as months 13..14 of prev year)
if ( $m <= 2 ) {
$y -= ( $adj = ( 14 - $m ) / 12 );
$m += 12 * $adj;
} elsif ( $m > 14 )
{
$y += ( $adj = ( $m - 3 ) / 12 );
$m -= 12 * $adj;
}
# make year positive (oh, for a use integer 'sane_div'!)
if ( $y < 0 ) {
$d -= 146097 * ( $adj = ( 399 - $y ) / 400 );
$y += 400 * $adj;
}
# add: day of month, days of previous 0-11 month period that began w/March,
# days of previous 0-399 year period that began w/March of a 400-multiple
# year), days of any 400-year periods before that, and 306 days to adjust
# from Mar 1, year 0-relative to Jan 1, year 1-relative (whew)
$d += ( $m * 367 - 1094 ) / 12 + $y % 100 * 1461 / 4 +
( $y / 100 * 36524 + $y / 400 ) - 306;
}