`
cocoIT
  • 浏览: 51018 次
  • 性别: Icon_minigender_1
  • 来自: 福建
文章分类
社区版块
存档分类
最新评论

JavaSE 8—新的时间和日期API

 
阅读更多
本文由ImportNew-胡 劲寒翻译自oracle。如需转载本文,请先参见文章末尾处的转载要求。

ImportNew注:如果你也对Java技术翻译分享感兴趣,欢迎加入我们的Java开发小组。参与方式请查看小组简介。

为什么我们需要一个新的时间日期API

Java开发中一直存在一个问题,JDK提供的时间日期API一直对开发者没有提供良好的支持。

比如,已有的的类(如java.util.DateSimpleDateFormatter)不是线程安全的,会在并发情况下留下一些隐患,这不是开发者在编写处理日期的代码块时想要的效果。

某些日期时间处理类也表现出了相当不合理的设计,比如在java.util.Date类中,年从1900开始,月从1开始,日从0开始——就表现的不是很直观。

这些问题导致我们会选择一些第三方的日期时间处理库,比如:Joda-Time

为了在JDK中解决这些问题并提供更好的方式,Java SE8中设计了新的时间日期处理API。

这个项目为JSR-310并由Joda-Time(Stephen Colebourne)和Oracle共同设计,并会放在Java SE 8的java.time包下。

核心思路

这个新的API由三个核心思路组成:

  • 不可改变值的类。一个严重的问题是,对于Java中已经存在的格式化处理类(Formatter)不是线程安全的。这使开发人员在日常开发中需要编写线程安全的日期处理代码变得很麻烦。新的API保证所有的核心类中的值是不可变的,避免了并发情况下带来的不必要的问题。

  • 领域驱动设计。新的API模型可以精确的表示出DateTime的差异性。在以前的Java库中这一点就表现的非常差。比如,java.util.Date他表示一个时间点,从Unix时代开始就是以毫秒数的形式保存,但是你调用它的toString方法时,结果却显示它是有时区概念的,这就容易让开发者产生歧义。

    领域驱动设计的重点是从长远好处出发且简单易懂, 当你需要把你以前的处理时间的模块代码移植到Java8上时你就需要考虑一下领域模型的设计了。

  • 区域化时间体系。新的API允许人们在时区不同的时间体系下使用。比如日本或者泰国,他们不必要遵循 ISO-8601。新API为大多数开发者减少了很多额外的负担,我们只需要使用标准的时间日期API。

LocalDate类和LocalTime类

LocalDate类和LocalTime类很有可能是你使用新API时第一个遇见的类。他们本地化的原因是他们能够根据系统环境来表示日期和时间,就像放在桌上的日历或者挂在墙上的时钟。还有一个混合类是LocalDateLocalTime组合而成的,叫LocalDateTime

当你不知道你所运行环境的时区时,你应该使用这些本地化的类。比如桌面JavaFX程序就是其中之一。甚至可以在处于不同时区的分布式系统中使用这些类。

现有的时间日期API中的类都不是线程安全的,开发者需要处理潜在的并发问题——这不是大部分的开发者想要的。

创建对象

在新的API中所有的核心类都可以由工厂方法很方便的构建。当我通过某些类自身的字段来构建它时,可以使用of方法;当我通过从另外一个类型的转换来构建它时,可以使用from方法。同样也可以通过parse方法来由一个String参数构建它。参见代码1.
代码1

1
2
3
4
5
6
LocalDateTime timePoint = LocalDateTime.now(
); // The current date and time
LocalDate.of(2012, Month.DECEMBER, 12); // from values
LocalDate.ofEpochDay(150); // middle of 1970
LocalTime.of(17, 18); // the train I took home today
LocalTime.parse("10:15:30"); // From a String

在Java SE 8 中我们可以使用Java标准的getter方法来获取想要的值,参见代码2

代码2

1
2
3
4
LocalDate theDate = timePoint.toLocalDate();
Month month = timePoint.getMonth();
int day = timePoint.getDayOfMonth();
timePoint.getSecond();

你也可以对对象的值进行运算操作。因为新的API中所有的类型都是不可变的,他们都是调用了with方法并返回一个新对象,相当于使用了setter赋值。对于每一个字段都有提供了基本的运算方法。参见代码3

代码3

1
2
3
4
5
6
7
8
// Set the value, returning a new object
LocalDateTime thePast = timePoint.withDayOfMonth(
10).withYear(2010);
/* You can use direct manipulation methods,
or pass a value and field pair */
LocalDateTime yetAnother = thePast.plusWeeks(
3).plus(3, ChronoUnit.WEEKS);

新的API提供的一个调节器的概念–用来封装通用的处理逻辑的一段代码。你对任意时间使用WithAdjuster来设置一个或者多个字段,或者可以使用PlusAdjuster来对字段进行增量或者减法操作. 值类型也可以被当做调节器使用,用来更新字段的值. 新的API定义了一些内置的调节器, 但是如果你希望实现某些特定的业务逻辑,你也可以自己实现一个调节器. 参见代码4。

代码4

1
2
3
4
5
6
7
8
import static java.time.temporal.TemporalAdjusters.*;
LocalDateTime timePoint = ...
foo = timePoint.with(lastDayOfMonth());
bar = timePoint.with(previousOrSame(ChronoUnit.WEDNESDAY));
// Using value classes as adjusters
timePoint.with(LocalTime.now());

截取

新的API提供了表示不同精度的时间点类型来表示日期、时刻、日期+时刻。

API提供的truncatedTo方法适用于这种场景:他允许你从一个字段中截取出一个值。参见代码5。

代码5

1
LocalTime truncatedTime = time.truncatedTo(ChronoUnit.SECONDS);

时区

我们参考了以前的对于时区的很复杂的抽象方式。时区就是一个规则的集合,同样的时区遵守同样的时间标准规定,时区大约有40条规则。时区是由世界统一时间(UTC)来定义的。 他们基本上是同步的但是也有细小的差别。时区有两种命名定义: 简写型, 比如, “PLT”,完整型,“Asia/Karachi.”。当你设计程序的时候,你应该考虑是在什么时区下运行。

  • ZoneId是时区的标示符. 每一个ZoneId都表示这些时区遵循同样的规则。 当你编码时你可以考虑使用例如“PLT”,“Asia/Karachi,”这种字符串来创建ZoneId。下面是一段完整的使用ZoneId的代码,参见代码6。

代码6

1
2
3
4
// You can specify the zone id when creating a zoned date time
ZoneId id = ZoneId.of("Europe/Paris");
ZonedDateTime zoned = ZonedDateTime.of(dateTime, id);
assertEquals(id, ZoneId.from(zoned));
  • ZoneOffset是一段时间内代表格林尼治时间/世界同一时间与时区之间的差异。他能表示一个特殊的差异时区偏移量。参见代码7。

代码7

1
ZoneOffset offset = ZoneOffset.of("+2:00");

时区类

  • ZonedDateTime是一个带有时区的日期时间类。他能表示出与任意时区的某个时间点的时差. 如果你希望代表一个日期和时间不依赖特定服务器环境, 你就应该使用ZonedDateTime.

代码8

1
ZonedDateTime.parse("2007-12-03T10:15:30+01:00[Europe/Paris]");
  • OffsetDateTime是一个带有偏移量的时间日期类。如果你的服务器处在不同的时区,他可以存入数据库中也可以用来记录某个准确的时间点。
  • OffsetTime是一个带有偏移量的时间类。参见代码9
    代码9
1
2
3
4
5
6
7
OffsetTime time = OffsetTime.now();
// changes offset, while keeping the same point on the timeline
OffsetTime sameTimeDifferentOffset = time.withOffsetSameInstant(offset);
// changes the offset, and updates the point on the timeline
OffsetTime changeTimeWithNewOffset = time.withOffsetSameLocal(offset);
// Can also create new object with altered fields as before
changeTimeWithNewOffset.withHour(3).plusSeconds(2);

Java中已经存在了表示时区的类—java.util.TimeZone—但是他不能用在Java SE 8中,因为在JSR-310中所有的时间日期类是不可变的,时区类确是可变的。

Period类

Periods类用来表示例如“三个月零一天”这种描述一段时间的值。这是目前看来与其他类不同的表示一段时间而不是时间点的类。 参见代码10。

代码10

1
2
3
4
5
6
7
8
// 3 years, 2 months, 1 day
Period period = Period.of(3, 2, 1);
// You can modify the values of dates using periods
LocalDate newDate = oldDate.plus(period);
ZonedDateTime newDateTime = oldDateTime.minus(period);
// Components of a Period are represented by ChronoUnit values
assertEquals(1, period.get(ChronoUnit.DAYS));

Duration类

Duration类也是用来描述一段时间的, 他和Period类似,但是不同于Period的是,它表示的精度更细。参见代码11。

1
2
3
// A duration of 3 seconds and 5 nanoseconds
Duration duration = Duration.ofSeconds(3, 5);
Duration oneDay = Duration.between(today, yesterday);

我们可以对其进行加减或者with函数操作,也可以使用它来修改一个时间日期对象的值。

Java SE 8 的java.time包中新的时间日期API的功能可用性和安全性都大大提升了。 新的API很好用,可以适应大部分的场景。

Chronology系列类

由于我们需要支持无ISO日期年表表示的环境, Java SE 8 首次引入了Chronology类, 在这种环境下使用。 他们也实现了核心的时间日期接口。
Chronology:
– ChronoLocalDate
– ChronoLocalDateTime
– ChronoZonedDateTime

这些类应该使用在具有高度国际化的应用中需要使用本地化的时间体系时,没有这种需求的话最好不要使用它们。有一些时间体系中甚至没有一个月,一个星期这样的概念,我们只能通过更加通用抽象的字段进行运算。

其余的API改动

Java SE 8 还提供了一些其他场景下使用的类.MonthDay类表示一个月中的某几天,表示节日的时候可以使用。YearMonth类可以用来表示在比如信用卡的生效和失效时间(译者注:信用卡失效时间以月为单位)。

Java SE 8中也提供了对于JDBC的新的类型支持, 但是是一个非公开的修改。

这些类也可以和某些数据库类型进行映射。如下表,描述了这些类对于ANSI SQL的对应关系

ANSI SQL Java SE 8
DATE LocalDate
TIME LocalTime
TIMESTAMP TIMESTAMP
TIMESTAMP WITH TIMEZONE OffsetDateTime

总结

Java SE 8提供的java.time中新的日期和时间API。很大的提升了安全性,功能也更为强大。新的API架构模型,会让开发人员在各种各样场景下很方面的使用。

原文链接:oracle翻译:ImportNew.com-胡 劲寒
译文链接:http://www.importnew.com/9635.html
[转载请保留原文出处、译者和译文链接。]

分享到:
评论

相关推荐

    JavaSE8 API文档

    4. **日期与时间API**:在Java 8中,`java.util.Date`和`java.util.Calendar`被新的日期时间API取代,包括`java.time.LocalDate`, `LocalTime`, `LocalDateTime`, `ZonedDateTime`, `Duration`和`Period`等类。...

    JavaSE原理-日期类API-MD笔记v1.2.pdf

    此外,Java 8的日期API还提供了丰富的操作方法,如加减日期、获取月份、星期等,使得日期和时间的计算变得更加简单和直观。例如,你可以轻松地计算两个日期之间的天数差: ```java import java.time.LocalDate; ...

    将JavaSE8的日期和时间类移植至JavaSE6和7中

    Java SE 8 引入了全新的日期和时间API,极大地改进了之前的`java.util.Date`和`java.util.Calendar`类的复杂性和不直观性。这个新的API,也被称为JSR-310,提供了更加易用、灵活且功能强大的类来处理日期、时间和...

    JavaSE6_API

    8. **国际化与本地化**:`java.text`和`java.util.Locale`类支持国际化和本地化,提供日期、时间、数字和消息的格式化。 9. **数据库访问**:JDBC(Java Database Connectivity)API在`java.sql`包中,用于连接和...

    JavaSE 7 API DOC

    10. **新的日期时间API**:`java.time`包提供了新的日期时间API,如`LocalDate`、`LocalTime`、`LocalDateTime`等,替代了原来的`java.util.Date`和`java.util.Calendar`,提供了更直观、更易用的日期时间处理功能。...

    javaSE jdk8 API帮助文档

    5. **日期与时间API的改进**:JDK8使用新的`java.time`包替换过时的`java.util.Date`和`java.util.Calendar`,提供了更强大且易于使用的日期和时间API。 6. **Optional类**:`java.util.Optional`类用于表示可能为...

    写给大忙人的JavaSE 8 中文版 + 英文版

    4. **日期和时间API**:JavaSE 8彻底改革了日期和时间处理,引入了java.time包,包括LocalDate、LocalTime、LocalDateTime和ZonedDateTime等类,替代了旧有的Calendar和Date类,使日期和时间操作更加直观和灵活。...

    JavaSE_JDK_API_中文版

    `java.util`则包含了集合框架、日期时间处理、随机数生成等工具类。 2. **类(Classes)**:每个类都代表了一种特定的数据结构或功能,如`ArrayList`、`HashMap`等。类定义了属性(fields)和方法(methods),通过...

    javase api 中文版

    8. **国际化与本地化**:`java.text`和`java.util.Locale`支持多语言环境,提供了日期、时间、数字和货币格式的处理。 9. **数据库连接**:JDBC(Java Database Connectivity)在`java.sql`包中,提供了与各种...

    javase-6-doc-api-zh_CN.zip

    13. **日期和时间API**:Java SE 6中的日期和时间处理主要依赖Calendar和Date类,虽然现在有更现代的java.time包,但在旧版本中这些仍是核心。 以上知识点只是Java SE 6 API中文文档的一部分,实际文档中还包括大量...

    JavaSE之日期时间类

    `java.time`包中的`LocalDate`、`LocalDateTime`、`ZonedDateTime`等类提供了更强大和灵活的日期时间操作,但这些是Java 8及更高版本才有的新特性。对于初学者来说,理解并掌握`java.util.Date`和`java.text....

    javase api

    这些API涵盖了各种功能,包括基本数据类型操作、对象模型、内存管理、输入输出、网络通信、多线程、集合框架、I/O流、XML处理、日期时间处理等。在Java开发中,Java SE API是开发者最常使用的工具之一。 源码分析是...

    Java SE 8_API

    4. **日期和时间API**:Java 8通过java.time包改进了日期和时间处理,替代了旧的java.util.Date和java.util.Calendar。新的API包括LocalDate、LocalTime、LocalDateTime、ZonedDateTime等,更易于使用且功能强大。 ...

    Java语言规范(JavaSE8)英文版

    5. **日期与时间API**:JavaSE8改进了日期和时间的处理,引入了`java.time`包,包含了诸如LocalDate、LocalTime、LocalDateTime和ZonedDateTime等类型,以及ChronoUnit、Period和Duration等时间间隔类,提供了更强大...

    javase8 api

    4. **日期和时间API**:Java 8对日期和时间处理进行了重大改进,引入了`java.time`包,包含了`LocalDate`, `LocalTime`, `LocalDateTime`, `ZonedDateTime`等类,替代了过时的`java.util.Date`和`Calendar`。新API...

    写给大忙人看的JavaSE8

    5. **日期和时间API**:JavaSE8彻底重构了日期和时间API,引入了`java.time`包,包含了`LocalDate`、`LocalTime`、`LocalDateTime`等类,提供了更加直观和强大的日期时间操作。 6. **流(Stream)**:JavaSE8引入的流...

    写给大忙人看的JavaSE 8

    JavaSE 8 对日期和时间的处理也进行了彻底的改进,引入了一个新的包`java.time`,其中包含了`LocalDate`、`LocalTime`、`LocalDateTime`等类,这些类的设计更为合理,使用起来也更加方便。与之前的`java.util.Date`...

    JavaSE_JavaSE学习资料_

    新版本的Java提供了更友好的日期时间API,使得处理日期和时间更加方便。正则表达式则是文本处理中的强大工具,可用于数据验证和模式匹配。 总的来说,这个JavaSE学习资料包将引导开发者全面地学习Java语言的核心...

    JavaSE1.8.rar

    5. **Date和Time API更新**:Java 8对日期和时间API进行了彻底的改造,引入了`java.time`包,提供了`LocalDate`、`LocalTime`、`LocalDateTime`等新类,取代了过时的`java.util.Date`和`Calendar`,使得日期和时间...

Global site tag (gtag.js) - Google Analytics