日期时间转换的极端情况的正确错误是什么?

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

TL;DR: 谓词 datime/2(由 SICStus Prolog 和 SWI-Prolog 提供)将 UNIX time 与包含年、月、日、时、分、秒。

对于一些极端情况,我得到了奇怪的答案,这让我想知道: 在这些情况下,符合 ISO 标准的 Prolog 系统应该引发哪些错误?


首先,这是 datime/2 documentation—part of the SICStus Prolog Manual:

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

<strong>datime(-Datime)</strong>     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.

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

所以这是一些虚假的 SICStus Prolog 4.6.0 输出:

| ?- 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

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

所以: 在这些情况下,符合 ISO 标准的 Prolog 系统应该引发哪些错误?

您想确定 Unix 时间戳值不合理地偏离“预期”范围的情况的适当错误。我不清楚负数是否有意义。但至少,它们似乎在 0..1972 年产生了合理的日期。第二个参数可能是一个适当的域,或者对于不可统一的术语来说只是失败。

从 7.12.2 中现有的 error classification 我们有以下候选人:

b) 类型错误。指定一个特殊类型似乎有点牵强。毕竟,即使是非负数也不应该有一个单独的类型,而是它们是一个域 not_less_than_zero.

c) 域错误。这似乎是一个不错的候选人。所以域可能是 unix_timestamp - 这应该是一个定义明确的数据类型;或 datime.

f) 表示错误。虽然类型和域错误意味着语义错误(“这样的时间不存在”),但表示错误却不会。它只是声明当前处理器无法表示该日期,但没有给出这可能意味着什么的结论。

所以我倾向于支持 f,仅仅是因为时间的概念似乎没有限制,即使对于年份(或时间戳)也是如此 7^7^7。我知道那是真正的乐观......

这两种实现似乎都存在一些实例化错误问题,SWI 产生的错误太多而 SICStus 不够——这个库在 SICStus 中相对较新,来自 Quintus 血统。

作为实例化错误的一般规则,请考虑 5.5.12 中新选项的要求。因此,如果第二个参数的实例是有效日期,则必须存在实例化错误。但是,如果没有有效的实例但组件仍然是变量,也可能会产生实例化错误。想一想 datime(T, datime(noyear,_,_,_,_,_)). 您可以为任何非基础术语产生实例化错误。