in reply to Question regarding Time::Piece and timezones

The behavior also appears to occur if I change my $t = localtime; to my $t = gmtime; as well, where the timezone is then 'UTC'.

That is very interesting. If I run your original code as posted (with Time::Piece 1.3401) with the TZ environment variable unset, it runs to completion and I see this output:

Time is: Thu, 14 Jan 2021 09:48:00 GMT Time is: Thu, 14 Jan 2021 09:48:00 UTC

Note that the textual representation of the timezone differs in the two lines of output.

If I subsequently re-run it with TZ set to apparently anything other than "GMT", then it bombs out. Even if I set it to "UTC" it will bomb out. This looks like a bug in Time::Piece .

Time is: Thu, 14 Jan 2021 10:03:32 UTC Error parsing time at /usr/local/lib64/perl5/Time/Piece.pm line 598. at tp.pl line 11. main::__ANON__("Error parsing time at /usr/local/lib64/perl5/Time/ +Piece.pm li"...) called at /usr/local/lib64/perl5/Time/Piece.pm line +598 Time::Piece::strptime("Time::Piece", "Thu, 14 Jan 2021 10:03:32 UT +C", "%a, %d %b %Y %T %Z") called at tp.pl line 23

🦛

Replies are listed 'Best First'.
Re^2: Question regarding Time::Piece and timezones
by atcroft (Abbot) on Jan 15, 2021 at 01:50 UTC

    Before I consider it a bug, I want to make sure the issue is not on my side or in my understanding. This is part of the reason my sample code attempted to go from object to string and back to object-to test both the strftime() and strptime() methods.

    My C is quite rusty (and I haven't dug around inside the perl source tree before), but it appears the process goes as follows when looking at the perl-5.30.3 source on MetaCPAN (PLEASE CORRECT ME IF YOU SPOT ANY ERRORS BELOW):

    1. When Time::Piece->strptime($time_string, $format_string) (found in cpan/Time::Piece/Piece.pm in the source distribution) is called, the format is first parsed by Time::Piece->_translate_format($format, $strptime_trans_map) . $strptime_trans_map appears to only contain the content of $trans_map_common (which defines formats 'c', 'r', and 'X', and NOT the formats 'e', 'D', 'F', 'R', 's', 'T', 'u', 'V', 'x', 'z', or 'Z', from $strftime_trans_map ).
    2. _strptime($string, $format, $islocal, $locales) (found in cpan/Time::Piece/Piece.xs) is then called. There are two such functions in Piece.xs:
      • line 345: static char * _strptime( pTHX_ const char buf*, const char *fmt, struct tm *tm, int *gotGMT )
      • line 1025: void _strptime ( string, format, got_GMT, SV* localization )
      Based on the signature, it appears the second (on line 1025) is called. After loading the locale data structure via _cpopulate_c_time_locale(aTHX_ locales ), this version of _strptime calls the version on line 345 as remainder = (char *)_strptime(aTHX_ string, format, &mytm, &gotGMT). If this returns with anything other than a '\0', either an "Error parsing time" or "Garbage at end of string in strptime:" message is returned.
    3. In _strptime( string, format, islocal, locales ) (to use the names from the original calls), when the "Z" character is found it appears to seek the end of the time zone name, then calls my_tzset(aTHX). According to perlguts, aTHX is an (a)rgument (TH)ingy(X).
    4. According to the comments, my_tzset(pTHX) ((p)rototype (TH)ingy(X)) is a wrapper to tzset() designed to make it work better on Win32. It does so by way of two #IFDEFs that determine if fix_win32_tzenv() is called. As my test failed on a Linux system, I do not believe the #IFDEFs are involved. tzset() (I believe from the system time.h) is then called.

    Questions:

    1. Are there any (obvious?) flaws in my tracing of the logic above?
    2. If indeed it is a bug (can someone confirm?), is it a problem with perl, or with a library used while compiling perl?

    Thank you for your time and attention. Stay safe!

Re^2: Question regarding Time::Piece and timezones
by Marshall (Canon) on Jan 23, 2021 at 02:21 UTC
    I agree that Time::Piece has a bug.