Posix time formatting is offset by locale

I guess there is a bug, if the current locale isn’t ‘C’:

/* SWI-Prolog 9.3.11, Windows 11 */
?- format_time(atom(X), '%a, %d %b %Y %H:%M:%S', 1725635101.000, posix).
X = 'Fri, 06 Sep 2024 17:05:01'.

I was rather expecting this result, i.e. correct GMT time:

?- atom_utctime(X, '%a, %d %b %Y %H:%M:%S', 1725635101000).
X = 'Fri, 06 Sep 2024 15:05:01'.

The above has the correct hour, whereas SWI-Prolog format_time/4
doesn’t show an GMT hour rather the locale hour. Which makes it
useless for rfc1123 I guess. But it is advertised as such.

You can check yourself:


https://www.epochconverter.com/

See also:

RFC 2616 - Hypertext Transfer Protocol – HTTP/1.1
All HTTP date/time stamps MUST be represented in
Greenwich Mean Time (GMT), without exception.
https://datatracker.ietf.org/doc/html/rfc2616#section-3.3.1

format_time/3,4 does not affect the timezone. If you want that, you need to first use stamp_date_time/3 to convert the time stamp to the desired timezone. The docs give the sample implementation for the HTTP time stamp:

        http_timestamp(Time, Atom) :-
                stamp_date_time(Time, Date, 'UTC'),
                format_time(atom(Atom),
                            '%a, %d %b %Y %T GMT',
                            Date, posix).

the posix just tells the system to use English day and month names and their abbreviations rather than the locale names.

Yeah thats better now, also shows the inconsistency more clearly:

?- stamp_date_time(1725635101.000, Date, 'UTC'), 
   format_time(atom(X), '%a, %d %b %Y %H:%M:%S GMT', Date, posix).
Date = date(2024, 9, 6, 15, 5, 1.0, 0, 'UTC', -),
X = 'Fri, 06 Sep 2024 15:05:01 GMT'.

?- format_time(atom(X), '%a, %d %b %Y %H:%M:%S GMT', 1725635101.000, posix).
X = 'Fri, 06 Sep 2024 17:05:01 GMT'.

Wouldn’t it be more useful if the API of format_time/4 also uses
stamp_date_time/3 with ‘UTC’ parameter when the argument
is a float? This is a little confusing, that I cannot fold a posix

timestamp into the format_time/4 call, when the flag says posix.

Edit 26.09.2024
Can you directly return posix timestamp for the current time
somewhere? Or do you not rely consistently on posix timestamp
whereever possible?

posix (locale) says nothing about timezones and you cannot tell the timezone from the stamp. That is why there is a stamp_date_time/3 to create a broken down time that does say something about the timezone. Of course we could have done that as part of format_time/4 by using options that both allows for controlling the timezone and locale (which defines the names and some more aspects of the text).

No clue what you want. get_time/1 gives you the current time. SWI-Prolog -- Dealing with time and date gives a lot of details on SWI-Prolog’s time handling.

It mostly follows standard practice in the Unix world: time stamps are UTC, time formatting by default uses the local time zone and locale formatting. But yes, an option for format_time/4 to both allow controlling the message format and the timezone interpretation might have been better.

Would be a good PIP topic :slight_smile:

I could repeat myself, but it seems futile. Last time, language (as controlled by the locale) and time zones are two different concepts. Surely, some languages are not widespread :slight_smile: Still, someone speaking such a language may travel around the world and see the local time in his/her familiar notation and language. Surely, several locales spread multiple time zones.

Surely, format_time/4 could have supported both in a a uniform interface rather than through a second predicate. I guess that is a bit of history that will hopefully be straightened out if there is enough enthusiasm to standardise this stuff. For now, it can do all reasonable common tasks without too much trouble.

1 Like

That was exactly what I challenged. I challenged it when I
mentioned a missing scan_time/[2,3] predicate:

The task that is missing is parsing formated times:

?- format_time(atom(X), '%a, %d %b %Y %H:%M:%S', 1725548701.0, posix).
X = 'Thu, 05 Sep 2024 17:05:01'.

?- parse_time('Thu, 05 Sep 2024 17:05:01', X).
X = 1725555901.0.

1725548701.0 and 1725555901.0 do not agree. There is also no
solution in sight using an additional step. The problem is that parse_time/2
doesn’t return a Date, but directly a time stamp. When there were a

Date, one could use date_time_stamp/3, but this later predicate
doesn’ exist either in SWI-Prolog.

There is no timezone info in this text?

This works:

?- format_time(atom(X), '%a, %d %b %Y %T %z', 1725548701.0),
   parse_time(X, Format, T).
X = 'Thu, 05 Sep 2024 18:05:01 +0300',
Format = rfc_1123,
T = 1725548701.0.

But of course this does have the timezone info in the parsed string, right?

For symmetry it might be a good idea to interpret missing time zone as local time?

Providing an interface to strptime() might be a good idea. I was not aware of it. Unfortunately Microsoft is too poor to spent time to implement it :frowning: Luckily there seem to exist some implementations for Windows, but that means another layer of complexity :frowning:

parse_time/3 should probably never have ended up in the library as it is far too limited and ambiguous :frowning: Probably we should simply document what it does and leave it alone.