In Perl, how would one efficiently parse the output of unix's date command, taking into account time zone, and also convert to UTC?
I've read many similar questions on stackoverflow, but few seem to take into account parsing multiple time zones. Instead they seem to set the timezone manually and assume it to stay fixed.
# Example Input Strings:
my @inputs = (
'Tue Oct 12 06:31:48 EDT 2010',
'Tue Oct 12 07:49:54 BST 2010',
);
I tried the following to no avail:
foreach my $input ( @inputs ) {
my $t = Time::Piece->strptime( $input,
'%a %b %d %T %Z %Y' );
print $t->cdate, "\n";
}
It seems the problem is the time zone (%Z). Additionally, a time zone field does not seem to exist in Time::Piece, which would require me to write custom code to convert to UTC, which just seems... wrong.
Context: I'm attempting to parse legacy logs from a variety of sources that use the unix date command for timestamps. Ideally, I'd like to convert all timestamps to UTC.
Any help would be greatly appreciated.
A few things you should know about Unix timestamps:Unix timestamps are always based on UTC (otherwise known as GMT). It is illogical to think of a Unix timestamp as being in any particular time zone. Unix timestamps do not account for leap seconds.
For timestamp with time zone , the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT ). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone.
In a computing context, an epoch is the date and time relative to which a computer's clock and timestamp values are determined. The epoch traditionally corresponds to 0 hours, 0 minutes, and 0 seconds (00:00:00) Coordinated Universal Time (UTC) on a specific date, which varies from system to system.
If you know how to disambiguate the TZs, just pop them into a dispatch table:
use strict; use warnings;
use DateTime::Format::Strptime ();
my @inputs = (
'Tue Oct 12 06:31:48 EDT 2010',
'Tue Oct 12 07:49:54 BST 2010',
);
my %tz_dispatch = (
EDT => build_parser( 'EST5EDT' ),
BST => build_parser( '+0100' ),
# ... etc
default => build_parser( ),
);
for my $input (@inputs) {
my ($parser, $date) = parse_tz( $input, %tz_dispatch );
print $parser->parse_datetime( $date ), "\n";
}
sub build_parser {
my ($tz) = @_;
my %conf = (
pattern => '%a %b %d %T %Z %Y',
on_error => 'croak',
);
@conf{qw/time_zone pattern/} = ($tz, '%a %b %d %T %Y')
if $tz;
return DateTime::Format::Strptime->new( %conf );
}
sub parse_tz {
my ($date, %tz_dispatch) = @_;
my (@date) = split /\s/, $date;
my $parser = $tz_dispatch{splice @date, 4, 1};
return $parser
? ($parser, join ' ', @date)
: ($tz_dispatch{default}, $date);
}
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