Java 8 时间日期库使用示例(二)

本文翻译:梁开权

在上一个章节中我们使用Java8提供的时间日期库,能更加便捷和灵活的操作时间日期,本章节我们将接着之前的内容继续跟大家分享Java8的时间日期库

如何增加时间里面的小时数

很多时候我们需要增加小时,分或者秒来计算出将来的时间。Java 8不仅提供了不可变且线程安全的类,它还提供了一些更方便的方法譬如plusHours()来替换原来的add()方法。

顺便说一下,这些方法返回的是一个新的LocalTime实例的引用,因为LocalTime是不可变的,可别忘了存储好这个新的引用。

LocalTime time = LocalTime.now();
LocalTime newTime = time.plusHours(2); // 加2个小时
System.out.println("两个小时后是 : " + newTime);
输出 :
两个小时后是 : 22:12:23.501

可以看到当前时间2小时后是22:12:23.501。现在你可以将它和Java中增加或者减少小时的老的方式进行下比较。一看便知哪种方式更好

如何获取1周后的日期

这与前一个获取2小时后的时间的例子类似,这里我们将学会如何获取到1周后的日期。LocalDate是用来表示无时间的日期的,它有一个plus()方法可以用来增加日,星期,或者月,ChronoUnit则用来表示这个时间单位。

由于LocalDate也是不可变的,因此任何修改操作都会返回一个新的实例,因此别忘了保存起来。

LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
System.out.println("今天是 : " + today);
System.out.println("一个星期后是 : " + nextWeek);
输出:
今天是 : 2018-04-01
一个星期后是 : 2018-04-08

可以看到7天也就是一周后的日期是什么。你可以用这个方法来增加一个月,一年,一小时,一分钟,甚至是十年,查看下Java API中的ChronoUnit类来获取更多选项。

一年前后的日期

这是上个例子的续集。上例中,我们学习了如何使用LocalDate的plus()方法来给日期增加日,周或者月,现在我们来学习下如何用minus()方法来找出一年前的那天。

LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
System.out.println("一年前是 : " + previousYear);
LocalDate nextYear = today.plus(1, YEARS);
System.out.println("一年后是 : " + nextYear);
输出:
一年前是 : 2017-04-01
一年后是 : 2019-04-01

可以看到现在一共有两年,一个是2017年,一个是2019年,分别是2018的前后那年。

在Java 8中使用时钟

Java 8中自带了一个Clock类,你可以用它来获取某个时区下当前的瞬时时间,日期或者时间。

可以用Clock来替代System.currentTimeInMillis()与 TimeZone.getDefault()方法。

// 返回你当前系统中的世界标准时间.
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock);
// 返回你当前系统中带有时区的时间
Clock.systemDefaultZone();
System.out.println("Clock : " + clock);
输出:
Clock : SystemClock[Z]
Clock : SystemClock[Asia/Shanghai]

在Java 8中,LocalDate类有一个isBefore()和isAfter()方法可以用来比较两个日期。

如果调用方法的那个日期比给定的日期要早的话,isBefore()方法会返回true。

LocalDate tomorrow = LocalDate.of(2018, 4, 2);
System.out.println("2018-04-02是未来的时间吗?" + tommorow.isAfter(today));
LocalDate yesterday = today.minus(1, DAYS);
System.out.println("2018-03-31是过去的时间吗?" + yesterday.isBefore(today));
输出:
2018-04-02是未来的时间吗?true
2018-03-31是过去的时间吗?true

可以看到在Java 8中进行日期比较非常简单。不需要再用像Calendar这样的另一个类来完成类似的任务了。

在Java 8中处理不同的时区

Java 8不仅将日期和时间进行了分离,同时还有时区。现在已经有好几组与时区相关的类了,比如ZonId代表的是某个特定的时区,而ZonedDateTime代表的是带时区的时间。它等同于Java 8以前的GregorianCalendar类。

使用这个类,你可以将本地时间转换成另一个时区中的对应时间,比如下面这个例子:

// 带有时区的日期和时间
ZoneId zId = ZoneId.of("GMT+8");
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZonedDateTime bj = ZonedDateTime.of(localtDateAndTime, zId );
System.out.println("当前时区的日期和时间 : " + bj);
输出:

当前时区的日期和时间 : 2019-01-05T11:48:18.122+08:00[GMT+08:00]

可以拿它跟之前将本地时间转换成GMT时间的方式进行下比较。顺便说一下,正如Java 8以前那样,对应时区的那个文本可别弄错了,否则你会碰到这么一个异常:

Exception in thread "main" java.time.zone.ZoneRulesException: Unknown time-zone ID: China/Bei_Jing
at java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:272)
at java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:227)
at java.time.ZoneRegion.ofId(ZoneRegion.java:120)
at java.time.ZoneId.of(ZoneId.java:403)
at java.time.ZoneId.of(ZoneId.java:351)

如何表示固定的日期

正如MonthDay表示的是某个重复出现的日子的,YearMonth又是另一个组合,它代表的是像信用卡还款日,定期存款到期日,options到期日这类的日期。

你可以用这个类来找出那个月有多少天,lengthOfMonth()这个方法返回的是这个YearMonth实例有多少天,这对于检查2月到底是28天还是29天可是非常有用的。

YearMonth currentYearMonth = YearMonth.now();
System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth());
YearMonth creditCardExpiry = YearMonth.of(2018, Month.FEBRUARY);
System.out.printf("你是信用卡在 %s 到期", creditCardExpiry);
输出:
当前年月的最后一天: 2019-01: 31
你是信用卡在 2018-02 到期

如何在Java 8中检查闰年

这并没什么复杂的,LocalDate类有一个isLeapYear()的方法能够返回当前LocalDate对应的那年是否是闰年。如果你还想重复造轮子的话,可以看下这段代码,这是纯用Java编写的判断某年是否是闰年的逻辑。

System.out.print("今年2019是闰年?" + today.isLeapYear()); //直接判断是否闰年
输出:
今年2019是闰年?false

你可以多检查几年看看结果是否正确,最好写一个单元测试来对正常年份和闰年进行下测试。

两个日期之间包含多少天,多少个月

还有一个常见的任务就是计算两个给定的日期之间包含多少天,多少周或者多少年。你可以用java.time.Period类来完成这个功能。在下面这个例子中,我们将计算当前日期与将来的一个日期之前一共隔着几个月。

LocalDate day = LocalDate.of(2018, Month.APRIL, 1);
LocalDate today = LocalDate.now();
Period period = Period.between(day , today);
System.out.println("2018年4月1日距离今天过去了多少个月: " + period.getMonths());
输出:
2018年4月1日距离今天间隔多少个月: 9

可以看到,现在是2019月1月,而2018年愚人节是4月1日,因此中间隔着9个月。

带时区偏移量的日期与时间

在Java 8里面,你可以用ZoneOffset类来代表某个时区,比如印度是GMT或者UTC5:30,你可以使用它的静态方法ZoneOffset.of()方法来获取对应的时区。只要获取到了这个偏移量,你就可以拿LocalDateTime和这个偏移量创建出一个OffsetDateTime。

LocalDateTime datetime = LocalDateTime.of(2018, Month.JANUARY, 14, 19, 30);
ZoneOffset offset = ZoneOffset.of("+05:30");
OffsetDateTime date = OffsetDateTime.of(datetime, offset);
System.out.println("带时区的日期和时间 : " + date);
输出:
带时区的日期和时间 : 2018-01-14T19:30+05:30

可以看到现在时间日期与时区是关联上了。还有一点就是,OffSetDateTime主要是给机器来理解的,如果是给人看的,可以使用ZoneDateTime类。

更多的内容我们可以在下个章节继续探讨

想获取更多技术视频,请前往叩丁狼官网:http://www.wolfcode.cn/openClassWeb_listDetail.html

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

推荐阅读更多精彩内容