0

Is it possible to convert a given timestamp to GMT in Perl using the POSIX module? Below is what I've tried, but not sure why the time is so far off...

use POSIX;
my $shipts = "2017-09-23 20:53:00";
my $shiptsgmt = strftime("%Y-%m-%d %R", localtime(str2time($shipts, 'GMT')));
print "$shiptsgmt\n";

The localtime of the server is Pacific time, guess what I'm trying to do is not correct. The above produces 2017-09-23 13:53 and I need 2017-09-24 03:53 time.

zdim
  • 64,580
  • 5
  • 52
  • 81
rwfitzy
  • 413
  • 5
  • 16
  • use POSIX allows for str2time. – rwfitzy Sep 26 '17 at 16:14
  • I don't see that in POSIX docs (v5.16 and v5.27) ... – zdim Sep 26 '17 at 16:29
  • @rwfitzy ? I have get `Undefined subroutine &main::str2time called at ...` – AnFi Sep 26 '17 at 16:31
  • POSIX.pm doesn't have any date-parsing utilities; it's not the best suited module for the job. – ikegami Sep 26 '17 at 16:55
  • Sorry, I see now it was actually coming from had Date::Parse used as well. Given this should be about that module instead of POSIX now, the solution was very simple to use gmtime instead of localtime as in gmtime(str2time($shipts)). Works! – rwfitzy Sep 26 '17 at 17:02

1 Answers1

3

The POSIX alone cannot do this, not without help from builtins and a little processing.

An alternative: Time::Piece is core, and in my experience much quicker than POSIX

perl -MTime::Piece -wE'
    $d = "2017-09-23 20:53:00"; 
    $t = localtime->strptime($d, "%Y-%m-%d %H:%M:%S");
    $t = gmtime($t->epoch);
    say $t->strftime("%Y-%m-%d %H:%M:%S");
'

This creates an object and then converts it to GMT using the module's (compatible) replacement for gmtime, returing an object which is also suitably flagged as GMT.

The strftime is the same but much lighter than the POSIX extension and strptime is from FreeBSD. The module also has many methods to get various parts or representations of the datetime object as a string, along with a few other utilities. See also Time::Seconds.

The DateTime does all this nicely, via its formatters for parsing and stringification. But it is heavy.


Note   It is rather easy to end up using this module incorrectly, and this answer did just that before ikegami fixed it. So please be very careful with any uses other than basic. See linked answers

Note that the answer above does not work in v5.10, apparently due to a then-bug in the module.

zdim
  • 64,580
  • 5
  • 52
  • 81
  • @ikegami Thank you. I've edited, with the info on your post that I now found which directly deals with that error (and another old post that this is apparently a dupe of). I'll add more suitable links if I find them. (I cleared some of my comments to make your warning more visible.) – zdim Sep 26 '17 at 19:49
  • @ikegami If I may bug you with a question. I've written a utility subclassing `Time::Piece` (carefully!) for particular uses here, and it works like a charm. But I could never find piece with this: Are there any glitches to this module, with edge cases, DST, days-without-midnight, or such? (Not counting trickiness and user errors.) I am thinking of fairly basic uses, for world-wide datetimes within the last century or so. I've searched and searched and found nothing to worry about but this is a tricky business. While one can't ask something like that here :( – zdim Sep 26 '17 at 19:54
  • It uses `localtime` for time zone stuff, so no issues of interest there. The problem with T::P is that it's easy to do things incorrectly with it. It's an API design failure, not a bug in the code. Subclassing might inherit those problems. Encapsulation might not. – ikegami Sep 26 '17 at 20:43
  • @ikegami Thank you very much for clearing that finally! And for the tip -- I got drawn to conveniencies but then I _am_ exposing the tricky parts this way, too (while I don't need all that). It's time to time things.. – zdim Sep 26 '17 at 22:50