Perl: Milliseconds to Date+Time

Viewed 1836

I am trying to convert a variable in Perl that contains milliseconds to date/time format. The catch is that variable came from mainframe TIMESTAMP that can not be converted by Unix/Linux because the duration, if I am not mistaken, starts in 1900-01-01 00:00:00. Thanks in advance.

perl:

my $milli_secs = ((hex(unpack('H*', substr($updt_time,0,3))) * 1099511627776) +
              (hex(unpack('H*', substr($updt_time,3,3))) * 65536) +
              (hex(unpack('H*', substr($updt_time,6,2)))));
$milli_secs = $milli_secs / 16;
$milli_secs = ($milli_secs * 3.90625) / 1000000;
print "$milli_secs\n";
my $tp = DateTime->from_epoch( epoch => $milli_secs );
print "Date ==> $tp\n";

Result: 3747753982164.99 Date ==> 120731-08-07T04:49:24

My variables: EBCDIC timestamp: D508FF8D00000000 With some calculations I have: Nano seconds: 3.74775398216499e+18 Milliseconds: 3747753982164.99

Which should give me (I think): 2018-10-05 18:46:22.1

3 Answers

You need to get the time value for 1900-01-01 and use it as your epoch:

use Time::Local;

my $epoch = timelocal(0,0,0,1,0,1900);

my $ms = 3747753982164.99;
my $time = $ms / 1000;

print scalar localtime $epoch + $time, "\n";

Outputs

Fri Oct  5 19:16:05 2018

Since you were using DateTime,

my $dt = DateTime->new( year => 1900, time_zone => "UTC" );
$dt->add( seconds => 3747753982164.99 / 1000 );
say $dt->strftime("%Y-%m-%dT%H:%M:%S.%06N%z");  # 2018-10-05T18:45:55.000000+0000

The conversions as translated from another language are far more complicated than needed. Building on ikegami's answer and the link provided in a comment, this works end-to-end:

use DateTime;
my $micros = hex(substr $updt_time, 0, 13);
my $dt = DateTime->new(year => 1900, time_zone => "UTC");
$dt->add(seconds => $micros / 1e6);
say $dt->strftime("%Y-%m-%dT%H:%M:%S.%06N%z"); # 2018-10-05T18:45:55.000000+0000
Related