Java8新特性-用法详解(二)日期类

JAVA8新特性-新的日期API

Java 8 另一个新增的重要特性就是引入了新的日期API,用更加简洁的方式处理时间和日期。具体的 API 放在 java.time 下。

日期API

旧API的缺陷

在 Java 8 之前,所有关于时间和日期的 API 都存在各方面的缺陷,比如:

  1. 日期类和时间类分开定义在 java.util.Date 和 java.util.Calendar 中,易用性差,不支持时区,而且是非线程安全的。
  2. 格式化日期类 DateFormat 位于 java.text 包中,而且是一个抽象类,我们必须实例化一个 SimpleDateFormat 对象才能格式化日期,并且 DateFormat 也不是线程安全的。这意味着如果你在多线程程序中调用同一个 DateFormat 对象,会得到意想不到的结果。
  3. Calendar 中的月份是从 0 开始的,需要加一才能表示当前月份。日期的计算方式十分繁琐,且易出错。
  4. 且 java.util.Date 同时包含日期和时间,而 java.sql.Date 中只包含日期,类名相同易混淆。
  5. 所有日期类都不是线程安全的,这是日期类最大的问题之一。
  6. 日期类不支持国际化,没有时区支持,虽然 java 引入了 java.util.Calendar 和 java.util.TimeZone ,但是并没有解决上面的问题。

由于以上这些问题,Java 需要一套用于处理日期和时间标准的框架,于是在 Java8 中引入了新的日期API。
与此同时还诞生了如Joda-Time,date4j等第三方的日期处理框架。
虽然 Java8 引用了新的时间处理类,但是 Joda-Time 的作者也参与了该设计。
如果您的项目依然是 JDK8 一下的版本,Joda-Time也是个不错的选择。

新API的优点

Java 8 中的日期和时间类,主要就是为了解决 7 以前的问题。下面就让我们来看看如何处理的。

  1. 不变性:新的日期/时间API中,所有的类都是不可变的,这对多线程环境有好处。
  2. 关注点分离:新的API将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date)、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类。
  3. 高效的使用了工厂模式和策略模式,类之间的协同工作变得简单。在所有类中都定义了 format() 和 parse() 方法,明确定义用以完成相同的行为,而不是像以前一个有一个单独的类。
  4. 实用操作:所有新的日期/时间API类都实现了一系列方法用以完成通用的任务,如:加、减、格式化、解析、从日期/时间中提取单独部分,等等。
  5. 可扩展性:新的日期/时间API是工作在ISO-8601日历系统上的,但我们也可以将其应用在非IOS的日历上。

API

java日期/时间API包含以下相应的包。

  1. java.time包:这是新的Java日期/时间API的基础包,所有的主要基础类都是这个包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有这些类都是不可变的和线程安全的,在绝大多数情况下,这些类能够有效地处理一些公共的需求。
  2. java.time.chrono包:这个包为非ISO的日历系统定义了一些泛化的API,我们可以扩展AbstractChronology类来创建自己的日历系统。
  3. java.time.format包:这个包包含能够格式化和解析日期时间对象的类,在绝大多数情况下,我们不应该直接使用它们,因为java.time包中相应的类已经提供了格式化和解析的方法。
  4. java.time.temporal包:这个包包含一些时态对象,我们可以用其找出关于日期/时间对象的某个特定日期或时间,比如说,可以找到某月的第一天或最后一天。你可以非常容易地认出这些方法,因为它们都具有“withXXX”的格式。
  5. java.time.zone包:这个包包含支持不同时区以及相关规则的类。

示例

2018-10-22 18:22:30:999999999 为例:

LocalDate日期

final LocalDate localDate = LocalDate.of(2018, 10, 22);
final LocalDate now = LocalDate.now(); // 获取当前日期 2018-10-22
final LocalDate ofYearDay = LocalDate.ofYearDay(2018, 295); // 第year年的第dayOfYear天 2018-10-22

localDate.getMonth(); // 月 10
localDate.getYear(); // 年 2018
localDate.getDayOfMonth(); // 日 22
localDate.getDayOfWeek(); // 星期 MONDAY
localDate.getDayOfYear(); // 天 295

LocalTime时间

其中纳秒最多可达 999999999.

final LocalTime of = LocalTime.of(18, 22); // 时-分 18:22
final LocalTime of1 = LocalTime.of(18, 22, 30); // 时-分-秒 18:22:30
final LocalTime of2 = LocalTime.of(18, 22, 30, 999999999); // 时-分-秒-纳秒 18:22:30.999999999

of.getHour(); // 时 18
of.getMinute(); // 分 22
of.getSecond(); // 秒 30
of.getNano(); // 纳秒 999999999

LocalDateTime

LocalDateTime 相当于 LocalDate + LocalTime 的合体,即包含日期和时间的类。

final LocalDateTime dateTime = LocalDateTime.of(2018, 10, 22, 18, 22, 30, 9999); // 年-月-日T时:分:秒:纳秒 2018-10-22T18:22:30.000009999
final LocalDateTime now = LocalDateTime.now(); // 当前时间 2018-10-22T18:22:30.000009999

// LocalDateTime 转为 LocalDate 和 LocalTime
dateTime.toLocalDate();
dateTime.toLocalTime();

// 将 LocalDate 转为 LocalDateTime
final LocalDate localDate = LocalDate.now(); // 2018-10-22
final LocalTime localTime = LocalTime.now(); // 18:22:30.000009999
final LocalDateTime localDateTime = localDate.atTime(localTime); // 2018-10-22T18:22:30.000009999

Instant

精确到纳秒的时间戳,与 System.currentTimeMillis() 类似。Instant 具有两个属性:seconds 毫秒数,nanos 纳秒值。

Instant instant = Instant.ofEpochSecond(120, 100000);
// 1970-01-01T00:02:00.000100Z

Duration

Duration 表示一个时间段,因此没有 now() 方法,与 Instant 类似。

LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 5, 10, 7, 0);    // 2017-01-05 10:07:00
LocalDateTime to = LocalDateTime.of(2017, Month.FEBRUARY, 5, 10, 7, 0);     // 2017-02-05 10:07:00
Duration duration = Duration.between(from, to);     // 表示从 2017-01-05 10:07:00 到 2017-02-05 10:07:00 这段时间

long days = duration.toDays();              // 这段时间的总天数
long hours = duration.toHours();            // 这段时间的小时数
long minutes = duration.toMinutes();        // 这段时间的分钟数
long seconds = duration.getSeconds();       // 这段时间的秒数
long milliSeconds = duration.toMillis();    // 这段时间的毫秒数
long nanoSeconds = duration.toNanos();      // 这段时间的纳秒数

也可以通过 of() 方法创建,接收时间长度和时间单位作为参数:

Duration duration1 = Duration.of(5, ChronoUnit.DAYS);       // 5天
Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS);  // 1000毫秒

日期操作和格式化

增加和减少日期


    LocalDateTime now = LocalDateTime.now();

    LocalDate date1 = date.plusYears(1); // 增加一年 2019-10-22
    LocalDate date2 = date.minusMonths(2);  // 减少两个月 2018-08-22
    LocalDate date3 = date.plus(5, ChronoUnit.DAYS); // 增加5天 2019-10-27

时区操作

新的时区类java.time.ZoneId是原有的java.util.TimeZone类的替代品。ZoneId对象可以通过ZoneId.of()方法创建,也可以通过ZoneId.systemDefault()获取系统默认时区。

所有的时区:
<p>
This maps as follows:
<ul>
<li>EST - -05:00</li>
<li>HST - -10:00</li>
<li>MST - -07:00</li>
<li>ACT - Australia/Darwin</li>
<li>AET - Australia/Sydney</li>
<li>AGT - America/Argentina/Buenos_Aires</li>
<li>ART - Africa/Cairo</li>
<li>AST - America/Anchorage</li>
<li>BET - America/Sao_Paulo</li>
<li>BST - Asia/Dhaka</li>
<li>CAT - Africa/Harare</li>
<li>CNT - America/St_Johns</li>
<li>CST - America/Chicago</li>
<li>CTT - Asia/Shanghai</li>
<li>EAT - Africa/Addis_Ababa</li>
<li>ECT - Europe/Paris</li>
<li>IET - America/Indiana/Indianapolis</li>
<li>IST - Asia/Kolkata</li>
<li>JST - Asia/Tokyo</li>
<li>MIT - Pacific/Apia</li>
<li>NET - Asia/Yerevan</li>
<li>NST - Pacific/Auckland</li>
<li>PLT - Asia/Karachi</li>
<li>PNT - America/Phoenix</li>
<li>PRT - America/Puerto_Rico</li>
<li>PST - America/Los_Angeles</li>
<li>SST - Pacific/Guadalcanal</li>
<li>VST - Asia/Ho_Chi_Minh</li>
</ul>
</p>
ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
ZoneId systemZoneId = ZoneId.systemDefault();
// 输出的话:[Asia/Shanghai]

参考:lw900925ImportNew - Justin Wu

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • 一、学习与成长 1.自控力第一章阅读+冥想五分钟 2.分享力训练营作业 二、社交 1.认识一个橙子学院小伙伴,住在...
    素娟Camellia阅读 198评论 0 0
  • 〈接上篇〉 戊三∶ 增上慧学者,即出世正见。 道谛,是三学,八正道。戒学,定学,都说过了,现在要说到慧学。慧学就是...
    顿律阅读 913评论 0 1
  • 小学六年级时我和她的友谊刚刚结合到一起,如同刚刚盛开的鲜花一般美丽。 虽然已经在一起学习五年了,但每天都形同陌路,...
    昔陌殇阅读 335评论 0 7
  • 我想,孤独应该就是不管你处于一个偌大或者狭小的空间里,只有你一个人,你可以拥有很多情绪和表情,却没有人在旁边陪衬你...
    安若暖儿阅读 198评论 0 1