convert the systemdate in iso 8601 format in perl
Asked Answered
E

4

14

I want the system date to be converted to ISO 8601 format. code:

my $now = time();
my $tz = strftime("%z", localtime($now));
$tz =~ s/(\d{2})(\d{2})/$1:$2/;
print "Time zone *******-> \"$tz\"\n";
# ISO8601
my $currentDate =  strftime("%Y-%m-%dT%H:%M:%S", localtime($now)) . $tz;
print "Current date *******-> \"$currentDate\"\n";

Current output is:

Time zone *******-> "-04:00"
Current date *******-> "2014-06-03T03:46:07-04:00"

I want the current date to be in format "2014-07-02T10:48:07.124Z", So that I can compute the difference between the two.

Ellsworth answered 3/6, 2014 at 7:47 Comment(3)
what module provides the strftime function?Queridas
@Queridas as a sub, not a method, usually it's POSIXPelaga
Naturally, others have already solved this: DateTime::Format::ISO8601Commando
H
17

You should use gmtime() instead of localtime() to get the broken-down time values in UTC.

use POSIX qw(strftime);
my $now = time();
print strftime('%Y-%m-%dT%H:%M:%SZ', gmtime($now)), "\n";

output:

2014-06-04T10:17:17Z
Hedonism answered 4/6, 2014 at 10:7 Comment(1)
You might want to use '%FT%TZ' as the string. Same format, but shorter, and explicitly selecting the ISO 8601 date format (%F) and ISO 8601 time format (%T) instead of engineering ISO 8601.Thies
J
15

Perl's DateTime package (on CPAN) can produce ISO8601 dates for you very easily, but, with one caveat.

The string returned by DateTime will be in UTC, but, without a timezone specifier. This SHOULD be fine, because according to the ISO8601 spec, if no timezone is specified, then UTC should be assumed. However, not all parsers obey the spec perfectly. To make my dates more robust I append a Z to the end of the string I get from DateTime, so this is the code I recommend:

use DateTime;
my $now = DateTime->now()->iso8601().'Z';
Jeff answered 29/4, 2015 at 18:15 Comment(3)
DateTime->now()->format_cldr("yyyy-MM-dd'T'HH:mm:ssZ") is a more dynamic (albeit verbose) way of appending the offset. In this case, +00:00 will be appended instead of Z, but that still suffices for ISO 8601.Treasatreason
@bart-b Do you have a reference to the ISO8601 spec saying that UTC should be assumed? I have only seeing documentation saying that local time is assumed if the Z is missing.Fire
DateTime->now->rfc3339 is better here, since it already supports adding in the timezone.Medellin
B
7

Time::Piece and Time::Seconds have been included as a standard part of Perl since 2007.

#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Time::Piece;

my $time = localtime;
say $time->datetime; # Time in ISO8601 format
say $time->tzoffset; # Time zone offset in seconds

# But tzoffset actually returns a Time::Seconds object
say $time->tzoffset->hours; # Time zone offset in hours (for example)
Bedim answered 3/6, 2014 at 9:35 Comment(3)
This script is not running on perl v5.8.8, for this Perl v5.10.0 required-Ellsworth
@DaveCross Time::Piece continues to be a part of Core Perl, and using modern features is not problematic-- especially since hardcoding line endings is far worse than enforcing a moderately recent version of Perl.Becalm
@VectorGorgoth: I am well aware that Time::Piece is still part of core Perl. I'm not sure why you think you need to remind me.Bedim
P
-2

This uses just standard packages:

#! /usr/bin/perl
use POSIX qw(strftime);
use Time::HiRes qw/gettimeofday/;
  
sub iso8601
{
  my ($s, $f) = split (/\./, gettimeofday);
  strftime ('%Y-%m-%dT%H:%M:%S.'.$f.'%z', localtime ($s))
}

print iso8601, "\n";
Physiological answered 15/7, 2021 at 13:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.