trealla-prolog / trealla

A compact, efficient Prolog interpreter written in plain-old C.
MIT License
268 stars 13 forks source link

Feature request: UTC time parsing #598

Open Jean-Luc-Picard-2021 opened 6 days ago

Jean-Luc-Picard-2021 commented 6 days ago

How would I parse UTC time. It seems that posix_strptime/2 doesn't convert between different time zones. Basically the field %Z seems to be accepted and parsed, but doesn't change the result?

?- posix_strptime('%d.%m.%Y %H:%M %Z', '14.11.2023 12:38 UTC', X).
   X = tm(0,38,12,14,10,123,2,317,0).

?- posix_strptime('%d.%m.%Y %H:%M %Z', '14.11.2023 13:38 CET', X).
   X = tm(0,38,13,14,10,123,2,317,0).

Maybe this is on purpose, since tm/1 is not supposed to be a UTC time, rather a time with an arbitrary reference point? If tm/1 would be a UTC time, the above two calls should return the same value.

Lets say we accept tm/1 to have an arbitrary referenc e point. How would we obtain an integer time with reference point UTC, for the two different inputs. There is only:

?- posix_mktime( tm(0,38,13,14,10,123,2,317,0), X).
   X = 1699965480.

What is missing is Pythons calendar.timegm.

infradig commented 4 days ago

man strptime:

glibc notes For reasons of symmetry, glibc tries to support for strptime() the same format characters as for strftime(3). (In most cases, the corresponding fields are parsed, but no field in tm is changed.)

Jean-Luc-Picard-2021 commented 3 days ago

I was expecting that posix_mktime is the culprit. But posix_strptime has also problems with UTC.

If the LC_TIME locale is not 'C' it might not accept rfc1123 dates correctly, i.e. the specifiers %a and %b.

Here is an implementation in Python, note the UTC flag:

def sys_time_parse(text, fmt, utc):
    if utc:
        locale.setlocale(locale.LC_TIME, (None, None))
        date = time.strptime(text, fmt)
        return calendar.timegm(date)*1000
    else:
        locale.setlocale(locale.LC_TIME, locale.getlocale())
        date = time.strptime(text, fmt)
        return int(time.mktime(date)*1000)

And here some test cases , local is de_CH:

?- atom_time('Mon, 23 Sep 2024 23:50:57', '%a, %d %b %Y %H:%M:%S', X).                   
Fehler: Kein Datum.

?- atom_time('Mo, 23 Sep 2024 23:50:57', '%a, %d %b %Y %H:%M:%S', X).
X = 1727128257000.

But I can't compare with SWI-Prolog. SWI-Prolog has only format_time/4 and no scan_time/4. But the last argument in format_time/4 acts

as the UTC flag in SWI-Prolog.