BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

JSR 310 Java Date与Time API

| 作者 Alex Blewitt 关注 4 他的粉丝 , Charles Humble 关注 930 他的粉丝 ,译者 张龙 关注 14 他的粉丝 发布于 2010年5月6日. 估计阅读时间: 7 分钟 | ArchSummit北京2018 共同探讨机器学习、信息安全、微服务治理的关键点

近日JSR 310 Date与Time API的领导Stephen Colebourne发布了该提案(准备加入到Java语言中)的早期草案。InfoQ有幸在QCon London上采访到了Stephen以深入了解该项目。

InfoQ:我们为何需要一个新的Date与Time API?现有的怎么了?

Stephen:目前API(java.util.Date与java.util.Calendar)的一个主要问题在于他们是可变的。换句话说,请看如下代码:

public class Employee {
  private final Date startDate;
  public Employee(Date date) {
    startDate = date;
  }
  public Date getDate() {
    return startDate;
  }
}

即便将startDate标识为final,但返回的java.util.Date实例依然是可变的,这样在外面就可以通过调用setYear()修改雇员的起始日期。此外,还有其他一些小问题,比如年份是从1900开始计算的而月份则从0开始,但关键问题还是可变性。这些问题没法修复。

InfoQ:在JSR 310中对应于java.util.Date的是什么?

Stephen:JSR 310实际上有两个日期概念。第一个是Instant,它大致对应于java.util.Date类,因为它代表了一个确定的时间点,即相对于标准Java纪元(1970年1月1日)的偏移量;但与java.util.Date类不同的是其精确到了纳秒级别。

第二个对应于人类自身的观念,比如LocalDateLocalTime。他们代表了一般的时区概念,要么是日期(不包含时间),要么是时间(不包含日期),类似于java.sql的表示方式。此外,还有一个MonthDay,它可以存储某人的生日(不包含年份)。每个类都在内部存储正确的数据而不是像java.util.Date那样利用午夜12点来区分日期,利用1970-01-01来表示时间。

InfoQ:你方才提到了时区这个令人苦恼的概念,在这方面,新的API有什么与众不同之处么?

Stephen:首先我们要区分时区(比如Europe/Paris与America/New_York)和距UTC的偏移量(比如+01:00与-08:00)之间的差别。偏移量仅仅是UTC和本地时间之间的差值,而时区则是一个具名的规则集合,描述了偏移量该如何随着时间的变化而变化。比如说,时区会描述一个特定的区域(如纽约)在给定的一个时刻具有某个偏移量,之后具有另一个偏移量(在本地时间线上创建一个间隙或是重叠,如春秋夏时制的变换等)。

有3个级别的类支持这些概念。LocalDateTime无需使用偏移量和时区就能表示时间。OffsetDateTime额外地指定了偏移量而ZonedDateTime则增加了时区规则。过去,很多应用都喜欢使用时区,但他们真正需要的其实只是偏移量而已(使用偏移量更简单、更快且不易出错)。XML Schema规范就是一个典型,它只支持偏移量而不支持时区。JSR 310可以明确表示出这些差别。

最后我想说的是,时区规则会随着时间的推移而不断发生变化。就在千禧年之前,一些国家将时区由国际日界线之后改为之前;此外,夏时制也在不断变化。比如说,美国最近将夏时制的开始时间推后了,这样现在已经进入了美国的夏时制而尚未进入欧洲的夏时制。还有一些国家几乎每年都在变化,比如巴西。JSR 310 API支持时区的版本化,新版的时区数据可以替换掉旧版的。虽然这种替换取决于具体的实现,但组织可以通过将新数据追加到类路径之前以将新规则加到现有的VM中,这样就无需更新整个JVM的安装文件了。

InfoQ:开始与结束时间之间的范围是如何界定的呢?

Stephen:可以使用Duration界定任意两个Instant之间的范围。对于目前使用了开始与结束日期的代码来说,这是最接近的类比。

如前所述,现在有一些具体的概念来表示YearMonthMonthDay,在适当的时候应该使用这两个类。还有一个Period类来表示任意的时间周期,如“两年、3个月、7天、4小时、50分钟”等。

InfoQ:那么其他日历如何呢?

Stephen:核心日历是ISOChronology,默认情况下使用它来映射时间,就像目前Java API中的GregorianCalendar一样。然而,我们对其他一些年代也提供了支持,如CopticChronologyThaiBuddhistChronology,如果需要还可以支持更多。

InfoQ:上面一些概念已经出现在了JodaTime中,那么JodaTime与JSR 310是什么关系呢?

Stephen:很多开发者已经开始使用JodaTime了,现在是时候改进Java基类了。最明显的变化就是包名(从org.joda.time变为javax.time),但实际上还有一些细小的差别。

首先,很多Joda Time API都接受null值来表示0时间或是间隔。虽然这么做很诱人,但这会导致大量的小错误(在没有恰当地返回值的情况下)。JSR 310通过抛出null参数异常修复了这个问题。

其次,与计算机相关的时间(Instant)和与人类相关的时间(DateTime)之间的差别变得更明显了。我们使用父接口InstantProvider替换掉之前的ReadableInstant以将任意时间转换为Instant。

第三,现在所有抛出的异常都是CalendricalExcpetion的子类。虽然CalendricalExcpetion是一个RuntimeException,但客户端的库调用都可以捕获这个父类。

InfoQ:最后我想问的是,目前JSR 310的状态如何?

Stephen:JSR 310专家组维护着一个开放的邮件列表,3周前也已经发布了规范的早期草案供大家审查。审查周期截止到3月28日;如果你有任何意见或建议,请直接发给dev@jsr-310.dev.java.net,或是在Expert Draft Review wiki上留下你的意见。

查看英文原文:JSR 310 Date and Time API for Java

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

沙发..看起来很诱人 by zhao joyous

这样的设置方法确实很诱人,我比较讨厌年份是从1900开始计算的而月份则从0开始.不过,我还在用1.4.2,并且固执的不愿意升级..

Re: 沙发..看起来很诱人 by Shine Jimmy

反正你不升级JDK,那么新的对你有什么用呢?

Re: 沙发..看起来很诱人 by YANG LiN

用joda-time一年多了

Re: 沙发..看起来很诱人 by zhao joyous

关注下

jdk的日期这一块处理的非常烂 by Ma Karl

RT

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

5 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT