Perl: Decoding timestamp in binary
I have a fixed width binary that I am decoding. One of the fields is a timestamp. It is 5 bytes long and formatted SS SS SS SS MS
. The first four bytes represent the seconds from 2000/01/01 00:00:00 data, and the byte MS
provides more precision by representing the number of 10ms interval in the second (values range from 0 to 99).
The encoding type for this field is binary. For example: response time 2008-4-28 14:42:51.15
, field is being filled 0F A8 9E EB 0F
.
How to parse and convert binary data to timestamp format in Perl?
source to share
The module Time::Piece
is suitable for this purpose, and it has been a core module since version 10 of Perl 5, so it shouldn't need to be installed.
It unpack
is also the most convenient way to extract data fields from a string.
It will look like this. I used pack
to create the file content that you described and I had to add fractional seconds to the result separately as it Time::Piece
doesn't support fractional seconds.
use strict;
use warnings;
use Time::Piece;
my $data = pack 'H*', '0FA89EEB0F';
print decode_timestamp($data), "\n";
sub decode_timestamp {
my ($seconds, $ms) = unpack 'N C', shift;
my $base = Time::Piece->strptime('2000-01-01', '%Y-%m-%d');
($base + $seconds)->strftime('%Y-%m-%d %H:%M:%S') . sprintf '.%02d', $ms;
}
Output
2008-04-28 14:42:51.15
source to share
use the Time :: Moment CPAN module:
use Time::Moment;
my $data = 0x0FA89EEB0F;
my $seconds = $data >> 8; # Right shift to remove fractional second.
my $milliseconds = 10 * ( $data & 0xff ); # Hundredths to Milli
my $tm = Time::Moment->new( year => 2000, month => 1, day => 1 ); #base datetime
my $tm2 = $tm->plus_seconds($seconds)->plus_milliseconds($milliseconds);
print $tm2, "\n"; #<-- prints: 2008-04-28T14:42:51.150Z
source to share