I have a fixed-width binary file that I'm decoding. One of the fields is the time stamp. It is 5 bytes long, and of the format SS SS SS SS MS. The first four bytes represents seconds from the data 2000/01/01 00:00:00 and the MS byte provides greater accuracy by representing the number of 10ms interval multiples within the second (value range is 0 to 99).
The Encoding type of this field is Binary. Eg: The answer time is 2008-4-28 14:42:51.15, the field is filled with 0F A8 9E EB 0F.
How do I parse and convert the binary data into the timestamp format in Perl?
The Time::Piece module is suitable for this purpose, and it has been a core module since version 10 of Perl 5 so it shouldn't need installing.
Also, unpack is the most convenient way to extract the data fields from the string.
It would look like this. I have used pack to create the file contents that you describe, and I had to append the fractional seconds to the result separately as Time::Piece doesn't support parts of a second.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With