时间间隔的包容性/独占性是否有标准?

Gus*_*Gus 42 java time date conventions

我想知道是否有一个标准或"正常"的方法来解释时间间隔数据终点相对于定义终点的值的包容性/排他性.但是请注意,我问的是标准(或最常见)约定是什么(如果有的话),而不是关于个人偏好的论文.如果您确实想要提供论文,请将其附加到某人发布的标准或有关该事项的标准文本的参考文献中.开放标准(我不需要付费阅读)是非常优选的,除非它们有根本缺陷:).

当然,从A到B的时间间隔有4种可能性:

  1. (A,B) - 两端都是独家的.
  2. [A,B] - 两端都是包容性的.
  3. [A,B) - 开始是包容性的,结束是独占的
  4. (A,B) - 开始是独占的,结束是包含的

每个都有不同的特点(我看到它,随意指出更多)

[A,B]惯例具有看似不方便的特性,即B包含在[A,B]和[B,C]中.如果B表示午夜边界并且您正试图确定它落在哪一天,这尤其不方便.此外,这意味着间隔的持续时间有点刺激,因为[A,B]其中A = B的长度应为1,因此[A,B]的持续时间为(B - A)+ 1

类似地,(A,B)惯例将难以使B既不属于(A,B)也不属于(B,C)......继续与日界的类比,午夜将是两天的一部分.这在逻辑上也是不方便的,因为[A,B]其中A = B是持续时间小于零的无感区间,但是反转A和B不会使其成为有效区间.

所以我想我想要[A,B]或(A,B),我无法弄清楚如何在它们之间做出决定.

因此,如果某人有标准文档的链接,请参考标准文本或类似内容,以澄清会很好的惯例.或者,如果您可以链接各种标准文档和/或或多或少完全不同意的参考文献,那么我可以选择一个似乎对CMA具有足够权限的文档和完成它:).

最后,我将使用Java,因此我特别容易得到在Java中运行良好的答案.

Voo*_*Voo 48

在一般情况下,[A, B)有很多事情要做,我没有看到为什么时间间隔不同的原因.

Djikstra写了一篇关于它的好文章为什么编号应该从零开始 - 尽管名称 - 主要处理这个问题.

简要总结优势:

  • end - start 等于列表中的项目数
  • 前一个区间的上限是下一个区间的下限
  • 允许使用无符号数[1]索引从0开始的间隔

就个人而言,第二点对于许多问题非常有用; 考虑一个非常标准的递归函数(在伪python中):

def foo(start, end):
    if end - start == 1:
        # base case
    else:
        middle = start + (end - start) / 2
        foo(start, middle)
        foo(middle, end)
Run Code Online (Sandbox Code Playgroud)

使用包含上限写入相同内容会引发许多错误,而这些错误可能会因一个错

[1]这是优势(A, B]- 从0开始的间隔比结束的间隔更常见MAX_VAL.注意,还涉及一个额外的问题:使用两个包含边界意味着我们可以表示其长度不能用相同大小表示的序列.

  • 我完全同意 [A,B) 是最好的,尤其是在午夜问题方面。`2014-01-01 00:00:00` - `2014-01-02 00:00:00`,当使用 [A,B) 解释时,包括整个 1 月 1 日。这正确地排除了 1 月 2 日的“2014-01-02 00:00:00”。 (2认同)

Bas*_*que 7

java.time & 半开放

取代麻烦的遗留日期时间类的java.time类以及 Joda-Time 项目使用半开放方法 [) 定义了一个时间跨度,其中开头是包容性的,而结尾是独占性的

对于带有小数秒的日期时间,这消除了试图捕获最后时刻的问题。必须解决无限可分的最后一秒,但各种系统使用各种粒度,例如毫秒、微秒、纳秒或其他。随着半开,一天,例如,在开始一天的第一时刻运行到,但包括下列天的第一时刻。问题解决了,无需与一天的最后一刻及其小数秒搏斗。

我已经看到在我所有的日期时间处理代码中始终如一地使用这种方法的好处。例如,从星期一开始的一周会持续到但不包括下一个星期一。一个月从 1 号开始,一直到(但不包括)下个月的第一天,因此忽略了确定该月最后一天(包括闰年 2 月 28 日/29 日)的编号的挑战。

持续使用半开放 [) 的另一个好处是,每次我必须检测、破译和验证一段代码的时间跨度方法时,都可以减轻认知负担。在我自己的编程中,我只需扫一眼顶部评论中提到的半开放,我立即知道如何阅读该代码。

一致使用半开放的结果是减少了我的代码中出现错误的机会,因为我的思维和写作风格是统一的,没有机会对包容-排他感到困惑。

顺便说一下,请注意半开 [) 意味着避免 SQLBETWEEN连接,因为它总是完全关闭的 []。

至于我服务的客户的商业思维,我会在适当的情况下尝试说服他们也经常使用半开。我见过很多不同的业务人员对报告中涵盖的时间段做出错误假设的情况。一致使用半开避免了这些不幸的歧义。但是如果客户坚持,我会在我的代码中注明这一点并调整输入/输出,以便在我自己的逻辑中使用半开。例如,我的逻辑使用星期一至星期一的一周,但在报告中减去一天以显示星期日。

有关使用半开放方法 [) 表示时间跨度的更多类,请参阅ThreeTen-Extras项目的Interval类(一对Instant对象)和LocalDateRange类(一对LocalDate对象)。


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。Hibernate 5 & JPA 2.2 支持java.timejava.sql.*

从哪里获得 java.time 类?


Gus*_*Gus 5

我将使用Voo的链接提供我为团队编写的内容作为答案,直到Voo添加答案为止,然后我会给他功劳。这是我对本案的决定:

我们的应用程序中的时间间隔将被表示为一对瞬时时间,约定开始时间为包含时间,结束时间为排除时间。此约定在数学上很方便,因为边界的差等于间隔的长度,并且在数值上与Java程序中数组和列表的下标方式一致(请参见http://www.cs.utexas.edu /~EWD/ewd08xx/EWD831.PDF)。实际的结果是,间隔2012-03-17T00:00:00.000Z – 2012-03-18T00:00:00.000Z表示圣帕特里克节的整个过程,从2012-03-17开始的每个日期都是标识为包含在圣帕特里克节中,但不包括2012-03-18T00:00:00.000Z,并且圣帕特里克节将恰好包含24 * 60 * 60 * 1000毫秒。


Iva*_*ali 5

尽管这个线程更多地关注 Java,但我认为看到其他采用的约定会非常有趣,特别是考虑到如今pandasPython在数据分析中无处不在,而且这个 StackOverflow 页面是热门搜索结果之一在寻找有关时间范围的包容性/排他性的约定时。

引用此页

严格包含开始日期和结束日期。因此,如果指定的话,它不会生成这些日期之外的任何日期。

此外,它不仅生成日期范围。当尝试索引时间序列数据时也采用该约定。这是对数据框的简单测试DatetimeIndex

>>> import pandas as pd
>>> pd.__version__
'0.20.2'
>>> df = pd.DataFrame(list(range(20)))
>>> df.index = pd.date_range(start="2017-07-01", periods=20)
>>> df["2017-07-01":"2017-07-05"]
            0
2017-07-01  0
2017-07-02  1
2017-07-03  2
2017-07-04  3
2017-07-05  4
Run Code Online (Sandbox Code Playgroud)