写点什么

☕【Java 技术指南】「Java8 编程专题」让你真正会用对 Java 新版日期时间 API 编程指南

发布于: 刚刚
☕【Java技术指南】「Java8编程专题」让你真正会用对Java新版日期时间API编程指南

技术背景

一切都源于 JSR-310 规范


  • JSR-310 规范提供一个新的和改进的 Java 日期与时间 API,会在 Java8 中包含,可以下载 OpenJDK 早期发布版本试用,详细信息可见:https://jdk8.java.net/download.html

  • JSR-310 规范领导者 Stephen Colebourne 就是 joda-time 作者,其主要思想也是借鉴了 joda-time,而不是直接把 joda-time 移植到 Java 平台中,API 是类似的,但做了改进和调整。

  • 具体规范请前往如下地址下载:https://jcp.org/en/jsr/detail?id=310

代替 Date 类的日期类(LocalXX 系列)

首当其冲的是 LocalDateTime、LocalDate、LocalTime ,提供了对 java.util.Date 的替代,另外还提供了新的 DateTimeFormatter 用于对格式化/解析的支持


  • 介绍相关的 XXX.now()的方法,这些太简单了,接下来介绍一下相关的较为特殊的用法,例如:

相对于 ZoneId.systemDefault()默认时区

LocalDateTime now = LocalDateTime.now();System.out.println(now);
复制代码


相当于使用默认时区时钟瞬时时间创建`Clock.systemDefaultZone()``;

相对于自定义时区

LocalDateTime now2= LocalDateTime.now(ZoneId.of("Europe/Paris"));System.out.println(now2);
复制代码


会以相应的时区显示日期:欧洲的巴黎时区

自定义时钟

Clock clock = Clock.system(ZoneId.of("Asia/Dhaka"));  LocalDateTime now3= LocalDateTime.now(clock);  System.out.println(now3);
复制代码


与上面的一样,会以相应的时区显示日期

定义时间数据

不需要写什么相对时间 如 java.util.Date 年是相对于 1900 月是从 0 开始


//2013-12-31 23:59  LocalDateTime d1 = LocalDateTime.of(2013, 12, 31, 23, 59);  
复制代码


//年月日 时分秒 纳秒LocalDateTime d2 = LocalDateTime.of(2013, 12, 31, 23, 59,59, 11);
复制代码

使用瞬时时间 + 时区

Instant instant = Instant.now();LocalDateTime d3 = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());System.out.println(d3);
复制代码

解析 String->LocalDateTime

LocalDateTime d4 = LocalDateTime.parse("2013-12-31T23:59");System.out.println(d4);
复制代码

999 毫秒 等价于 999000000 纳秒

LocalDateTime d5 = LocalDateTime.parse("2013-12-31T23:59:59.999");System.out.println(d5);
复制代码

使用 DateTimeFormatter API 解析和格式化

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");LocalDateTime d6 = LocalDateTime.parse("2013/12/31 23:59:59", formatter);  System.out.println(formatter.format(d6));  
复制代码

时间属性的获取

System.out.println(d6.getYear());  //获取年份System.out.println(d6.getMonth());  //获取月份System.out.println(d6.getDayOfYear());  // 获取当年的第几天System.out.println(d6.getDayOfMonth());//获取属于本月的第几天System.out.println(d6.getDayOfWeek());// 获取相对于本周的日期System.out.println(d6.getHour());// 小时System.out.println(d6.getMinute());  //分钟System.out.println(d6.getSecond());  // 秒数System.out.println(d6.getNano());  //纳秒数
复制代码

时间增减

LocalDateTime d7 = d6.minusDays(1);  LocalDateTime d8 = d7.plus(1, IsoFields.QUARTER_YEARS);  
复制代码

代替 System.currentTimeMillis()的瞬时对象(Instant)

瞬时时间,等价于以前的 System.currentTimeMillis()


  • 瞬时时间 相当于以前的 System.currentTimeMillis()


Instant instant1 = Instant.now();//精确到秒 得到相对于1970-01-01 00:00:00 UTC的一个时间System.out.println(instant1.getEpochSecond());//精确到毫秒System.out.println(instant1.toEpochMilli()); 
复制代码


  • 获取系统 UTC 默认时钟


Clock clock1 = Clock.systemUTC(); //得到时钟的瞬时时间Instant instant2 = Instant.now(clock1);System.out.println(instant2.toEpochMilli());
复制代码


  • 固定瞬时时间时钟


Clock clock2 = Clock.fixed(instant1, ZoneId.systemDefault()); Instant instant3 = Instant.now(clock2);//得到时钟的瞬时时间  System.out.println(instant3.toEpochMilli());//与上面的 instant1代表的含义一样!
复制代码

Clock 时钟

类似于钟表的概念,提供了如系统时钟、固定时钟、特定时区的时钟


//时钟提供给我们用于访问某个特定 时区的 瞬时时间、日期和时间的。

系统默认 UTC 时钟(当前瞬时时间 System.currentTimeMillis())

Clock c1 = Clock.systemUTC(); System.out.println(c1.millis()); //每次调用将返回当前瞬时时间(UTC)  
复制代码

系统默认时区时钟(当前瞬时时间)

Clock c2 = Clock.systemDefaultZone(); Clock c31 = Clock.system(ZoneId.of("Europe/Paris")); //巴黎时区  System.out.println(c31.millis()); //每次调用将返回当前瞬时时间(UTC)  
复制代码


Clock c32 = Clock.system(ZoneId.of("Asia/Shanghai"));//上海时区  System.out.println(c32.millis());//每次调用将返回当前瞬时时间(UTC)  
复制代码


Clock c4 = Clock.fixed(Instant.now(), ZoneId.of("Asia/Shanghai"));//固定上海时区时钟  System.out.println(c4.millis());  Thread.sleep(1000);  System.out.println(c4.millis()); //不变 即时钟时钟在那一个点不动  
复制代码


Clock c5 = Clock.offset(c1, Duration.ofSeconds(2)); //相对于系统默认时钟两秒的时钟  System.out.println(c1.millis());  System.out.println(c5.millis());  
复制代码

ZonedDateTime

  • 带有时区的 date-time 存储纳秒、时区和时差(避免与本地 date-time 歧义);API 和 LocalDateTime 类似。

  • API 和 LocalDateTime 类似,只是多了时差(如 2013-12-20T10:35:50.711+08:00[Asia/Shanghai])


ZonedDateTime now = ZonedDateTime.now();System.out.println(now);
复制代码


ZonedDateTime now2= ZonedDateTime.now(ZoneId.of("Europe/Paris"));  System.out.println(now2);
复制代码


其他的用法也是类似的 就不介绍了


ZonedDateTime z1 = ZonedDateTime.parse("2013-12-31T23:59:59Z[Europe/Paris]");System.out.println(z1);
复制代码

Duration

表示两个瞬时时间的时间段


Duration d1 = Duration.between(Instant.ofEpochMilli(System.currentTimeMillis() - 12323123), Instant.now());//得到相应的时差System.out.println(d1.toDays());  System.out.println(d1.toHours());  System.out.println(d1.toMinutes());  System.out.println(d1.toMillis());  System.out.println(d1.toNanos());  
//1天时差 类似的还有如ofHours() Duration d2 = Duration.ofDays(1); System.out.println(d2.ofHours());
复制代码

Calendar 的替代者 Chronology

Chronology 用于对年历系统的支持,是 java.util.Calendar 的替代者


//提供对java.util.Calendar的替换,提供对年历系统的支持  Chronology c  = HijrahChronology.INSTANCE; ChronoLocalDateTime d = c.localDateTime(LocalDateTime.now());  System.out.println(d);  
复制代码

年、年月、月日、周期的 API 支持

Year year = Year.now();  YearMonth yearMonth = YearMonth.now();MonthDay monthDay = MonthDay.now();System.out.println(year);//年  System.out.println(yearMonth); //年-月  System.out.println(monthDay); // 月-日  
复制代码

Period 日期层面的间隔时间

周期,如表示 10 天前 3 年 5 个月


Period period1 = Period.ofDays(10);System.out.println(period1);Period period2 = Period.of(3, 5, 0);System.out.println(period2);
复制代码

参考文章

http://www.codedata.com.tw/java/jodatime-jsr310-1-date-calendar/http://www.codedata.com.tw/java/jodatime-jsr310-2-time-abc/http://www.codedata.com.tw/java/jodatime-jsr310-3-using-jodatime/

用户头像

🏆 2021年InfoQ写作平台-签约作者 🏆 2020.03.25 加入

【个人简介】酷爱计算机技术、醉心开发编程、喜爱健身运动、热衷悬疑推理的”极客狂人“ 【技术格言】任何足够先进的技术都与魔法无异 【技术范畴】Java领域、Spring生态、MySQL专项、APM专题及微服务/分布式体系等

评论

发布
暂无评论
☕【Java技术指南】「Java8编程专题」让你真正会用对Java新版日期时间API编程指南