【问题标题】:What is the right error for corner cases of datetime conversion?对于日期时间转换的极端情况,正确的错误是什么?
【发布时间】:2021-04-19 12:39:40
【问题描述】:

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

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


首先,这是datime/2 documentation——SICStus Prolog Manual 的一部分:

<strong>now(-When)</strong>    将当前日期和时间统一为带有When 的UNIX 时间戳。

<strong>datime(-Datime)</strong>    将Datime 与当前日期和时间统一为datime/6 形式的datime(Year,Month,Day,Hour,Min,Sec) 记录。所有字段都是整数。

<strong>datime(+When,-Datime)</strong> <strong>datime(-When,+Datime)</strong>    将now/1 获得的时间戳转换为datime/6 记录。 可以双向使用。

所以这是一些虚假的 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 系统应该引发哪些错误?

【问题讨论】:

  • 我认为您可以 1) 保持 ISO 兼容或 2) 有有意义的例外。但不是两者兼而有之。
  • @DavidTonhofer:你能举一 (1) 个例子来证实你的观点吗?
  • @false 如果我说 Java 没有在语言规范中列出允许的异常集就足够了吗?但是没关系:“合同违反”或“断言失败”也不例外。
  • @DavidTonhofer:到目前为止,您还没有给出一个具体示例来说明您最初的争论。你只是做了一些非常抽象的评论。
  • @DavidTonhofer。让我们继续关注 Prolog。我不能同时担心 Prolog 和 Java。

标签: prolog iso-prolog


【解决方案1】:

如果 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,_,_,_,_,_)).,您甚至可以为任何非基本术语产生实例化错误。

【讨论】:

  • 假设我选择representation_error...由于实际值不是error/2 复合的一部分,我可以使用representation_error(datetime) 两种模式(+,-) (-,+) ?
  • 我不太担心这个极端案例,它已经超过了 2525 年......不过,原则上,我想避免诉诸“沉默失败”。
  • (-,+) 你到底是什么意思?太大的年份是可以的。但是超值呢?至少在 SWI 中,您似乎也可以放更大的值。这样您就可以轻松确定时间戳,例如距当前时间戳 100 天。或 1000 秒等。
  • 我喜欢这样。它有点草率,但有时是有用的。我想我需要编写一个程序来了解底层函数的确切限制。
  • OTOH 允许更大的值,比如天数意味着 datime/2 不会是一个关系......
猜你喜欢
  • 1970-01-01
  • 2018-12-21
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 2015-07-30
  • 2023-04-02
  • 1970-01-01
  • 2021-07-23
相关资源
最近更新 更多