不同编程语言中的库如何处理Date&时间,时间戳和持续时间,Leapseconds& - 年,DST&时区, ...?

时间:2010-09-14 14:32:43

标签: c# python language-agnostic date time

是否存在标准组织或特定的规范方式,如何在实践中实现与时间相关的事情(如ICU用于与Unicode相关的任务),或者目前这是“尽力而为”,取决于语言和图书馆实施者想花多少精力,时间和金钱?

是否有一个具体而完整的实施可以作为如何处理与时间有关的事情的一个例子?

您认为哪个现有的图书馆是一个糟糕的,体面的或好的例子?

6 个答案:

答案 0 :(得分:17)

我将尝试使用可能成为Java 7一部分的Java库来回答第二个和第三个问题。

javax.time。*(JSR 310)

这些类是对JodaTime的完全重写,试图解决util.Date / util.Time以及JodaTime的设计缺陷。

JSR 310尝试提供日期和时间的综合模型,这是一种类型安全和自我记录的模型。它可与现有类互操作,但也可考虑基于XML和DBMS的用例。 这些类是最终的,不可变的,线程安全的,并且在构造之后不能修改。实例是通过一组丰富的Factory方法创建的,这些方法可以在后台缓存内容。

LocalDate dateToday     = LocalDate.of(2010, 9, 14);
LocalDate oneMonthLater = dateToday.with(OCTOBER);
LocalDate oneYearLater  = dateToday.withYear(2011);

API有一些“面向机器”的类和一些“以人为本”的类:

机化

<强> Instant

与Unix或Java时间戳相当的时间点。实际上有InstantTAIInstantUTCInstant,可让人们准确选择他们需要的时间定义。即“基于日期”,“线性,无闰秒”等。

<强> Duration

不一定与特定日期或日历相关联的时间范围。

以人为本

有一个丰富的类集合,处理不同的用例,如仅限日期,仅限时间,时间和日期,有和没有时区,有和没有DST。

<强> DateProvider

OffsetDateLocalDate(,java.sql.Date兼容性)

<强> TimeProvider

OffsetTimeLocalTime(,java.sql.Time兼容性)

<强> DateTimeProvider

ZonedDateTimeOffsetDateTimeLocalDateTime(,java.util.GregorianCalendar兼容性)

<强> InstantProvider

InstantZonedDateTimeOffsetDateTime(,java.util.Date兼容性)

<强> Period

句点代表“5天”的时间跨度,可以在日期/时间中加上和减去。

<强> Matcher

匹配器启用查询,例如“这是2006年的日期吗?”或“这一天是今年的最后一天”。

<强> Adjuster

如果您想要进行更复杂的更改,例如“给我这个月的最后一天!”,调节员会来救援。或者“圣诞节后的第二个星期二,拜托!”。

<强> Resolver

解析器允许用户定义在特定日期无效时应该发生的情况,例如2010年2月31日:

DateResolver previous = DateResolvers.previousValid();
LocalDate date = date(2010, 2, 30, previous);
// date = 2010-02-28

使用时区和DST数据

可以序列化这些类,并使用当前时区数据或序列化时区数据对它们进行反序列化。 另外,可以比较来自不同时区的规则:可以找出DST规则是否已经改变,例如: G。版本2010e和2010f之间的伦敦或莫斯科日期,并决定如果时间有差距或重叠应该怎么做。

日历系统

虽然一切都基于ISO-8601,但提供了希伯来语,Hijrah,日语,ThaiBuddist等时间系统的简单日历。

格式化和解析

toString()会返回ISO8601,并支持SimpleDateFormat中更高级的模式。

<强>集成

  • 数据库
  • JodaTime
  • 旧版JDK课程(java.util.*
  • XML

<强> 参考文献:

答案 1 :(得分:11)

有时间和日期(日历)
第一个问题是日期与时间无关,而与厄尔,月亮等的天文位置无关。+人类活动的规律性/周期性。时间也是主观的,相对的,甚至是相对论的,并且可以是天文学上的,也可以是原子的。

时间正文和日期/日历正文
国际标准化组织(ISO) [4]已发布

  • “ISO 8601数据元素和交换格式 - 信息交换 - 日期和时间的表示”[4a]

与其他国际标准一样,是建议,并以已经建立的做法为基础 它(主观地)仅基于格里高利历[5]和普通历法(在实际发明之前向后投射,因此在处理历史日期时用途有限)[5a]。

世界日历协会[1d]自2012年开始引入新的世界日历[1b-1d],这将使无用的现有日期库成为现实。同样,同样的主要问题,请进一步查看。

我曾经看到,IT系统中与日期时间相关的比较最多的是[2] BIG8 DBMS(IBM DB2,Informix,Ingres,InterBase,Microsoft SQL Server,MySQL,Oracle和Sybase)。登记/> 这个和所有其他调查表明,处理相同,例如,公历日历时间/日期在所有系统之间以及同一平台内(不同产品和同一产品的版本之间)不同,请参阅例如,[3]。

所有系统中的所有日期/时间库的主要问题,框架是他们的日期/时间数据类型不允许在日期/时间数据类型中包含地理和日历信息即可。
没有它,它们主要是半无用的 - 7世纪SQL Server datetime2值的毫秒意义是什么?当时甚至没有时钟测量时间,准确度为分钟(Galileo Galilei使用,例如,他的心跳测量他的实验中的时间间隔)以及格里高利历甚至没有被发明。

因此,大量的日期时间类型空间被滥用,未能通过将日期与地理位置和/或日历信息相关联并将其包含在日期中来提供最重要的灵活性。

快速插图:

  • 现代俄罗斯使用格里高利历,俄罗斯东正教使用朱利安历法确定俄罗斯的许多州假日(例如,俄罗斯的圣诞节是1月7日,旧年是1月14日的格里高利历。其他宗教节日的日期相对于格里高利历而言是浮动的。)
  • 在1917年之前的俄罗斯,波兰作为其一部分,使用格里高利历,而所有其余的俄罗斯使用朱利安历法(在“同一”时区浮动差异为13-18天)[5b];
  • 双击MS Windows中的时钟(或打开控制面板 - &gt;日期和时间) - &gt;时区标签 - &gt;查看组合框中的时区。你会看到格林尼治标准时间-12:00到格林尼治标准时间+ 13:00有超过一百个时区的25小时,格林威治标准时间+ 5:00,格林尼治标准时间+5:30,格林威治标准时间+5:45等小时。

====引用:
[1]新世界日历
[1a] 更新:对不起,请不要阅读[1a],作者混淆了日历并在本新闻简报中写错了信息
2012年世界日历:一个月内35天 http://www.panorama.am/en/society/2010/01/29/newcalendar
[1b] http://en.wikipedia.org/wiki/World_Calendar
[1c] http://www.theworldcalendarin2012.org/Index2.htm
[1d] http://www.theworldcalendar.org/TWCA.htm

[2] Peter Gulutzan,Trudy Pelzer。 SQL性能调优:SQL中的日期 http://www.informit.com/articles/printerfriendly.aspx?p=30939

[3] SqlDateTime.MinValue!= C#DateTime.MinValue,为什么?
SqlDateTime.MinValue != DateTime.MinValue, why?

[4]
国际标准化组织
http://en.wikipedia.org/wiki/International_Organization_for_Standardization
[4a] ISO 8601数据元素和交换格式 - 信息交换 - 日期和时间的表示
http://en.wikipedia.org/wiki/ISO_8601

[5]
阳历日历
http://en.wikipedia.org/wiki/Gregorian_calendar
[5a] Proleptic Gregorian calendar
http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
[5b]公历采用
http://en.wikipedia.org/wiki/Gregorian_calendar#Adoption
[6]
http://en.wikipedia.org/wiki/Galileo_Galilei

答案 2 :(得分:10)

我认为此刻此类事情没有单一的标准,但是有多种标准可以符合这些标准:例如ISO 8601。

ICU自己的日期/时间处理是一种跨语言(C / C ++和Java)和多平台库。

它在内部处理日期和时间,通常一次使用UDate(C / C ++)或java.util.Date/long(Java),自1-1-1970以来的毫秒数,或者日历对象,特定于日历类型(Gregorian vs Hijri等)。持续时间可用于格式化。闰年计算为日历系统的一部分,并假设闰秒由底层操作系统处理。 DST /时区数据保持最新,其中“tz数据库”有时由其作者姓氏Olson提及。

希望这已经回答了一些关于ICU的问题。

答案 3 :(得分:7)

我暂时没有使用它,但从过去的经验来看,我会说Boost.Date_Time是一个很好的例子。

虽然可能不是今天许多快节奏项目的首选,但C ++的表现力似乎仍然非常适合像日期/时间这样复杂的问题领域,因此结合高质量的同行评审流程来传递为了成为一个官方的Boost C ++库,我希望手头的库可以作为一个例子来说明应该如何处理与时间相关的事情,尽管不是完整的实现,见下文。

提升日期时间

图书馆记录非常,所以我可能会用引号汇总整个答案,但我会尝试根据soc's answer建议的模板提取一些片段 - 尽管如此,我将从一个完整的引语开始:

动机

  

这个库的动机来自于在多个项目中使用并帮助构建多个日期时间库。 [...]

     

使用日期和日程编程   时间应该几乎一样简单   自然地用字符串编程   和整数。批量申请   时间逻辑可以从根本上说   通过拥有一套强大的简化   运营商和计算   能力。课程应该提供   能够比较日期和   次,增加长度或持续时间,   从时钟中检索日期和时间,   并自然地与日期和时间一起工作   间隔。

域概念

该库支持3种基本时间类型:

  • 时间点 - 时间连续体中某个位置的说明符。
  • 时间持续时间 - 未连接到时间连续体上任何点的时间长度。
  • 时间间隔 - 连接到时间连续体中特定点的持续时间。也被称为时间段。

计算

您可以在Details - Calculations部分中非常直观地了解域概念如何相互关联。

约束

我最初决定评估图书馆的一个重要部分是根据复杂的问题领域提供设计目标和必要权衡的可用文档,这似乎概述了已经放入图书馆的现实世界专业知识 - 您可以在以下两个部分中阅读更多相关内容:

使用时区和DST数据

就我所关注的问题而言,完全支持所有可以想到的计算和转换 - 请参阅Examples部分中的标题以获得初步印象。

日历/时间系统

这绝对是关于您的规范的弱点,尽管库是专门设计的,具有可扩展性:

  

该库的大部分起源是观察到很少有日期时间库以允许定制和扩展的方式构建。一个典型的例子,日历逻辑直接构建在日期类中。或者时钟检索功能直接构建在时间类中。这些设计决策通常使得无法扩展或更改库行为。在更基础的层面上,通常有关于时间表示或格里高历的解决方案的假设。

但是,我不了解其他日历/时间系统的实现情况,请参阅Library Reference了解当前的实施情况:

  • 日期时间
  • 阳历
  • Posix Time
  • 当地时间

格式化和解析

由于底层C ++ I / O系统各自的强大功能,完全支持这是库的一个优点,请参阅Date Time Input/Output - 面向流的C ++ I / O既有优点也有问题依赖关于您的需求和期望,但本主题将在本网站的其他地方讨论。

集成

这是provided as well通过与Boost Serialization的兼容性,虽然这是 archive ,但通常意味着二进制数据,文本数据,XML 文件>左右;即,JSR 310示例中未明确支持数据库。

答案 4 :(得分:4)

要回答“好示例”问题,请查看Noda Time - Jon SkeetJoda-Time库的Java端口到.Net

答案 5 :(得分:4)

你在之前的评论中提到了Python。

Python的内置datetime支持(docs)非常实用,但您必须使用第三方时区数据库(例如pytz (docs)才能完成此操作。并且,正如pytz文档提到的那样,如果你不小心的话,你可能仍然会在DST过渡期间添加增量来解决问题。

曾经的情况是,如果日期时间没有为您的应用程序执行此操作,eGenix的mx.DateTime是可行的,特别是对于字符串到时间戳的转换,但dateutil似乎很受欢迎(虽然我没用过它。)