What is the right error for corner cases of datetime conversion?

94 Views Asked by At

TL;DR:     The predicate datime/2 (offered by SICStus Prolog and SWI-Prolog) relates UNIX time to a record containing year, month, day, hour, minute, and second.

For some corner cases I got weird answers which made me wonder: Which error(s) should ISO-compliant Prolog systems raise in these cases?


First, here's the datime/2 documentation—part of the SICStus Prolog Manual:

now(-When)     Unifies the current date and time as a UNIX timestamp with When.

datime(-Datime)     Unifies Datime with the current date and time as a datime/6 record of the form datime(Year,Month,Day,Hour,Min,Sec). All fields are integers.

datime(+When,-Datime) datime(-When,+Datime)     Convert a time stamp, as obtained by now/1, to a datime/6 record. Can be used in both directions.

So here is some spurious SICStus Prolog 4.6.0 output:

| ?- use_module(library(system)).
yes
| ?- datime(X,Y).
no                           % expected: result | error
| ?- datime(-67768200000000000,X).
no                           % expected: result | error
| ?- datime(X,datime(19700000000000,1,1,1,0,0)).
X = -32029950380687608 ? ;   % expected: X >= 0
no

And here come some weird "answers" given by SWI-Prolog 8.2.0:

?- use_module(library(dialect/sicstus/system)).
true.

?- datime(X,datime(1970,1,1,1,0,0)).
ERROR: Arguments are not sufficiently instantiated
% expected: X = 0

?- datime(10000000000000000000000000,X).
X = datime(1901, 1461302465, 32753, 9, 35, 13).

?- datime(1000000000000000000000000000,X).
X = datime(1901, 1461302465, 32753, 9, 35, 13).

?- datime(100000000000000000000000000000,X).
X = datime(1901, 1461302465, 32753, 9, 35, 13).
% expected: different answers for different queries

So: Which error(s) should a ISO-compliant Prolog system raise in these cases?

1

There are 1 best solutions below

6
On BEST ANSWER

You want to determine the appropriate error for cases were the Unix timestamp value is unreasonably off the "intended" range. It is unclear to me whether or not negative numbers make sense. But at least, they seem to produce reasonable dates in the years 0..1972. The second argument could be a proper domain, or simply fail for non-unifiable terms.

From the existing error classification in 7.12.2 we have the following candidates:

b) a type error. Designating a special type seems a bit too far fetched. After all, not even the non-negative numbers deserve a separate type, instead they are a domain not_less_than_zero.

c) a domain error. This seems to be a good candidate. So the domain may be unix_timestamp - should that be a well defined data type; or datime.

f) a representation error. While type and domain errors imply semantic failure ("such a time cannot exist"), a representation error doesn't. It just states that the current processor cannot represent that date but no conclusion is given about what this could mean.

So I have some tendency to favor f, simply because the notion of time does not seem to have a limit not even for the year (or timestamp) 7^7^7. I know that is true optimism...

Both implementations seem to have some problems with instantiation errors, SWI produces too many of them and SICStus not enough - this library is relatively new in SICStus and from Quintus descent.

As a general rule for instantiation errors, consider what is required for new options in 5.5.12. So if an instance of the second argument is a valid date, then there has to be an instantiation error. But the instantiation error may also be produced, if there is no instance that is valid but where a component is still a variable. Think of datime(T, datime(noyear,_,_,_,_,_)). You could go as far as producing the instantiation error for any nonground term.