一、简介 从 Java 1.0 开始,就提供了对日期与时间处理的 java.util.Date 类,它允许把日期解释为年、月、日、小时、分钟和秒值,也允许格式化和解析日期字符串。不过,这些函数的 API 不易于实现国际化。在升级版本到 Java 1.1 前,Java 维护者认为 Date 类很难被重新构造,由于这个原因,Java 1.1 增加了一个新的 java.util.Calendar 类。Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和解析日期字符串。可是在开发者使用过程中感受到,Calendar 类并不比 Date 类好用,它们面临的部分问题是:
可变性:像时间和日期这样的类应该是不可变的。
偏移性:Date 中的年份是从 1900 开始的,而月份是从 0 开始的,不太符合常识习惯。
类命名:Date 并不表示处理”日期”,而”Calendar”类也不全是表示”日历”,类命名比较不合理。
格式化:时间日期格式化只对 Date 有用,Calendar 则不行,且时间格式化对象存在线程安全问题。
自 2001 年起 Joda-Time 项目发布,它提供了简单易用且线程安全的时间类库,很快在 Java 社区中流行并广泛使用。Java 维护人员考虑到 JDK 中也需要一个这样的库,于是就与巴西的 Michael Nascimento Santos 合作,Java 官方 JDK 新增了的时间/日期 API的进程(JSR-310)。
二、新时间 API 的组成 新增的时间 API 由 5 个包组成,如下:
三、概念 一些基础概念有助于我们更加理解时间类,所以我们需要了解一下。
1、时间与时刻
时间: 可以表示准确的时刻或日期,也可以表示一个时间段。
时刻: 指某一瞬bai间,表示具体的某一时间点,只是时间中的一个点。
2、时间戳和时区
时间戳: 时间戳是指格林尼治时间1970年01月01日00时00分00秒到现在的总秒数(毫秒数),可以理解成绝对时间,它与时区无关,不同时区对同一时间戳的解读不一样
时区: 同一时刻(时间戳),世界上各地区的时间可能是不一样的,具体时间与时区相关,按经度一共分为24个时区,英国格林尼治是0时区,中国北京是东8区
3、GM 和 UTC 每个地区都有自己的本地时间,在网上以及无线电通信中时间转换的问题就显得格外突出。整个地球分为二十四时区,每个时区都有自己的本地时间。在国际无线电通信场合,为了统一起见,使用一个统一的时间,都与英国伦敦的本地时相同:
GMT: Greenwich Mean Time 格林尼治标准时间。
UTC: Coordinated Universal Time 协调世界时,又称世界统一时间,世界标准时间,国际协调时间。
例如,北京时区是东八区,领先 UTC 八个小时,在电子邮件信头的 Date 域记为+0800,如果在电子邮件的信头中有这么一行 Date:Fri, 08 Nov 2020 10:30:00 +0800 说明信件的发送地的地方时间是 **2020 年 11 月 8 号,星期五,早上 10:30:00,这个地方的本地时领先 UTC 8 个小时(+0800,就是东八区时间)**。电子邮件信头的 Date 域使用二十四小时的时钟,而不使用 AM 和 PM 来标记上下午。
以上面电子邮件的发送时间为例,如果要把这个时间转化为UTC,可以使用一下公式:
时区差东为正,西为负。在此,把东八区时区差记为 +0800,
那么 UTC 时间为:
4、UTC 和 GMT 差别 简单的说 UTC 和 GMT 基本相等,但是 UTC 比 GMT 时间更为精准 ,他们区别如下:
UTC 是我们现在用得时间标准,GMT 是老的时间计量标准。
UTC 是根据原子钟来计算时间,GMT 是根据地球的自转和公转来计算时间,也就是太阳每天经过英国伦敦郊区的皇家格林威治天文台的时间就是中午12点。
由于现在世界上最精确的原子钟50亿年才会误差1秒(最精确原子钟问世:50亿年误差一秒),可以说非常精确。而 GMT 因为是根据地球的转动来计算时间的,而地球的自转正在缓速变慢,所以使用 GMT 的话,总有一天可能会变为,显示中午12点,但是实际并不是一天太阳当头照的时候,很可能就是早上或晚上。所以 UTC 更加精确。
5、时间输出格式类型
输出类型
描述
2019-06-10T03:48:20.847Z
世界标准时间,T:日期和时间分隔,Z:世界标准时间
2019-06-10T11:51:48.872
不含时区信息的时间
2019-06-10T11:55:04.421+08:00[Asia/Shanghai]
包含时区信息的时间,+08:00 表示相对于0时区加 8 小时,[Asia/Shanghai]:时区
四、主要类介绍 JDK 8 新时间 API 中增加了很多处理时间的类,主要有如下:
Instant: 表示时刻,即时间线上的一个瞬时点,精确到纳秒,常用于获取纪元时的秒、毫秒等时间戳,它提供了一系列的 minusXxx() 方法用于在当前时刻基础减去一段时间,也提供了 plusXxx() 方法在当前时刻基础加上一段时间;
Clock: 表示时钟,此类常用于查找当前时刻,也用于获取指定时区的日期、时间,该类可以取代 System.currentTimeMillis() 方法,也提供了很多获取当前日期、时间的方法;
Duration: 表示持续时间,此类以秒和纳秒为单位对时间量进行建模,常用于处理两个日期的时间段。
LocalDate: 表示日期(内部不记录时区),通常由”年”、”月”、”日”组成,该类封装了很多操作日期的方法。例如,当前日期加上或者减去几天、几月、几年等;
LocalTime: 表示时间(内部不记录时区),通常由”时”、”分”、”秒”组成,该类封装了很多操作时间的方法。例如,当前时间加上或者减去几秒、几分、几小时等;
LocalDateTime: 表示日期时间(内部不记录时区),是”时间”与”日期”的组合,该类封装了很多操作时间日期的方法,例如,当前时间加上或者减去几年、几月、几时、几分、几秒等;
ZoneDateTime: 表示日期时间(内部记录时区),方法和 LocalDateTime 类似;
Period: 表示基于日期的时间量,用年、月和日来模拟时间的数量或数量;
ZoneId: 表示时区,”+01:00”和”Europe/Paris” ZoneId 除了处理与标准时间的时间差还处理地区时(夏令时,冬令时等)
ZoneOffset: 表示时区偏移量,ZoneOffset 是 ZoneId 的子类,相对于格林尼治时间(GMT)的时间偏差,只处理与格林尼治的时间差;
五、常用示例 新的时间 API 提供了很多时间操作类和方法,不过常用的是 LocalDate 和 LocalDateTime,下面是各个类的方法使用示例,可以简单看看,在实际中如果是需要可以参考使用:
1、Instant 表示时刻,时间线上的一个瞬时点,常用于获取纪元时的秒、毫秒等时间戳。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 1import java.time.Instant; 2import java.time.temporal.ChronoUnit; 3import java.util.Date; 4 5public class InstantExample { 6 7 public static void instantTransition () { Instant instant = Instant.now(); long microsecond = instant.getNano(); long millisecond = instant.toEpochMilli(); long second = instant.getEpochSecond(); System.out.println("获取当前时刻:" + instant); System.out.println("获取当前时间的纳秒:" + microsecond); System.out.println("获取当前时刻按纪元时转换后的毫秒:" + millisecond); System.out.println("获取当前时刻按纪元时转换后的秒:" + second); System.out.println("-------------------------------------------------" ); } public static void instantCompare () { Instant instant1 = Instant.ofEpochMilli(1591113400000L ); Instant instant2 = Instant.ofEpochMilli(1591113410000L ); int difference = instant1.compareTo(instant2); boolean isAfter = instant1.isAfter(instant2); boolean isBefore = instant1.isBefore(instant2); System.out.println("比较 instant1 是否在 instant2 时刻之后:" + isAfter); System.out.println("比较 instant1 是否在 instant2 时刻之前:" + isBefore); System.out.println("比较 Instant 对象的差值:" + difference); System.out.println("-------------------------------------------------" ); } public static void instantCalculation () { Instant instant = Instant.now(); Instant instantPlus = instant.plus(3 , ChronoUnit.DAYS); Instant instantMinus = instant.minus(6 , ChronoUnit.DAYS); System.out.println("计算3天后的时刻:" + instantPlus); System.out.println("计算6天前的时刻:" + instantMinus); Instant instant1 = Instant.ofEpochMilli(1591113400000L ); Instant instant2 = Instant.ofEpochMilli(1591113410000L ); long diffAsMinutes = ChronoUnit.SECONDS.between(instant1, instant2); System.out.println("计算两个 Instant 之间的分钟数:" + diffAsMinutes); System.out.println("-------------------------------------------------" ); } public static void instantStaticMethod () { Instant epochSecond = Instant.ofEpochSecond(1591113458L ); Instant epochSecondNano = Instant.ofEpochSecond(1591113458L , 100 ); Instant epochMilli = Instant.ofEpochMilli(1591113458000L ); Date date = new Date (); Instant dateInstant = Instant.ofEpochMilli(date.getTime()); Date instantDate = new Date (Instant.now().toEpochMilli()); System.out.println("通过纪元时(秒)获取时刻:" + epochSecond); System.out.println("通过纪元时(秒)获取时刻并设置纳秒:" + epochSecondNano); System.out.println("通过纪元时(毫秒)获取时刻" + epochMilli); System.out.println("Date 转换 Instant 对象:" + dateInstant); System.out.println("Instant 转换 Date 对象:" + instantDate); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { instantTransition(); instantCompare(); instantCalculation(); instantStaticMethod(); } }
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ------------------------------------------------- 获取当前时刻:2020-07-06T15:00:07.860Z 获取当前时间的纳秒:860000000 获取当前时刻按纪元时转换后的毫秒:1594047607860 获取当前时刻按纪元时转换后的秒:1594047607 ------------------------------------------------- ------------------------------------------------- 比较 instant1 是否在 instant2 时刻之后:false 比较 instant1 是否在 instant2 时刻之前:true 比较 Instant 对象的差值:-1 ------------------------------------------------- ------------------------------------------------- 计算3天后的时刻:2020-07-09T15:00:07.917Z 计算6天前的时刻:2020-06-30T15:00:07.917Z 计算两个 Instant 之间的分钟数:10 ------------------------------------------------- ------------------------------------------------- 通过纪元时(秒)获取时刻:2020-06-02T15:57:38Z 通过纪元时(秒)获取时刻并设置纳秒:2020-06-02T15:57:38.000000100Z 通过纪元时(毫秒)获取时刻2020-06-02T15:57:38Z Date 转换 Instant 对象:2020-07-06T15:00:07.918Z Instant 转换 Date 对象:Mon Jul 06 23:00:07 CST 2020 -------------------------------------------------
2、Clock 表示时钟,此类常用于查找当前时刻。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import java.time.Clock;import java.time.Instant;import java.time.ZoneId;public class ClockExample { public static void getClock () { Clock utcClock = Clock.systemUTC(); Clock systemZoneClock = Clock.systemDefaultZone(); Clock zoneClock = Clock.system(ZoneId.of("Asia/Shanghai" )); Clock fixedClock = Clock.fixed(Instant.now(), ZoneId.of("Asia/Shanghai" )); System.out.println("获取\"系统时间\"的时钟,并使用\"UTC时区\"对日期和时间进行转换:" + utcClock); System.out.println("获取\"系统时间\"的时钟,并使用\"系统时区\"对日期和时间进行转换:" + systemZoneClock); System.out.println("获取\"系统时间\"的时钟,并使用\"指定时区\"对日期和时间进行转换:" + zoneClock); System.out.println("获取\"固定时刻\"的时钟,并\"指定时区\"对日期和时间进行转换:" + fixedClock); System.out.println("-------------------------------------------------" ); } public static void clockMethod () { Clock clock = Clock.systemDefaultZone(); Instant instant = clock.instant(); long millis = clock.millis(); ZoneId zoneId = clock.getZone(); Clock zoneClock = clock.withZone(ZoneId.of("Asia/Shanghai" )); System.out.println("获取当前时间的时钟,并使用UTC时区对日期和时间进行转换:" + clock); System.out.println("获取时钟的当前时刻:" + instant); System.out.println("获取时钟的当前毫秒瞬间:" + millis); System.out.println("获取用于创建日期和时间的时区:" + zoneId); System.out.println("返回带有不同时区的此时钟的副本:" + zoneClock); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { getClock(); clockMethod(); } }
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 -------------------------------------------------------------------------------------------------- 获取"系统时间" 的时钟,并使用"UTC时区" 对日期和时间进行转换:SystemClock[Z] 获取"系统时间" 的时钟,并使用"系统时区" 对日期和时间进行转换:SystemClock[Asia/Shanghai] 获取"系统时间" 的时钟,并使用"指定时区" 对日期和时间进行转换:SystemClock[Asia/Shanghai] 获取"固定时刻" 的时钟,并"指定时区" 对日期和时间进行转换:FixedClock[2020-07-06T14:56:56.362Z,Asia/Shanghai] -------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------- 获取当前时间的时钟,并使用UTC时区对日期和时间进行转换:SystemClock[Asia/Shanghai] 获取时钟的当前时刻:2020-07-06T14:56:56.372Z 获取时钟的当前毫秒瞬间:1594047416372 获取用于创建日期和时间的时区:Asia/Shanghai 返回带有不同时区的此时钟的副本:SystemClock[Asia/Shanghai] --------------------------------------------------------------------------------------------------
3、Duration 表示时间段,此类以秒和纳秒为单位对时间量进行建模,也用于处理两个日期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.time.Duration;import java.time.LocalDateTime;public class DurationExample { public static void dateDuration () { LocalDateTime time1 = LocalDateTime.of(2018 , 6 ,18 ,10 ,20 ,30 ); LocalDateTime time2 = LocalDateTime.of(2020 , 8 ,22 ,12 ,20 ,30 ); Duration duration = Duration.between(time1, time2); System.out.println("小时时间段:" + duration.toHours()); System.out.println("分钟时间段:" + duration.toMinutes()); System.out.println("秒时间段:" + duration.getSeconds()); System.out.println("毫秒时间段:" + duration.toMillis()); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { dateDuration(); } }
输出如下:
1 2 3 4 5 6 7 ------------------------------------------------- 小时时间段:19106 分钟时间段:1146360 秒时间段:68781600 毫秒时间段:68781600000 -------------------------------------------------
4、LocalDate 表示日期,通常由”年”、”月”、”日”组成,该类封装了很多操作日期的方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 import java.time.LocalDate;import java.time.format.DateTimeFormatter;public class LocalDateExample { public static void localDateTransition () { LocalDate localDate = LocalDate.now(); String formatLocalDate = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd" )); LocalDate ymdLocalDate = LocalDate.of(2020 , 6 , 18 ); LocalDate ydLocalDate = LocalDate.ofYearDay(2020 , 100 ); LocalDate epochDayLocalDate = LocalDate.ofEpochDay(10 ); System.out.println("在默认时区中从系统时钟获取当前日期:" + localDate); System.out.println("使用指定的格式化程序格式化此日期:" + formatLocalDate); System.out.println("根据设置年、月、日参数获取日期实例:" + ymdLocalDate); System.out.println("指定年和年中的天数参数获取日期实例:" + ydLocalDate); System.out.println("通过纪元时(天)获取日期实例:" + epochDayLocalDate); System.out.println("-------------------------------------------------" ); } public static void localDateCompare () { LocalDate localDate1 = LocalDate.of(2020 , 6 , 18 ); LocalDate localDate2 = LocalDate.of(2020 , 6 , 17 ); int difference = localDate1.compareTo(localDate2); boolean isAfter = localDate1.isAfter(localDate2); boolean isBefore = localDate1.isBefore(localDate2); System.out.println("比较 LocalDate 对象的差值:" + difference); System.out.println("检查此日期是否在指定的日期之后:" + isAfter); System.out.println("检查此日期是否在指定的日期之前:" + isBefore); System.out.println("-------------------------------------------------" ); } public static void localDateCalculation () { LocalDate localDate = LocalDate.now(); LocalDate plusLocalDate = localDate.plusDays(10 ); LocalDate minusLocalDate = localDate.minusDays(10 ); System.out.println("获取在当前日期基础(增加)指定(天数)的日期:" + plusLocalDate); System.out.println("获取在当前日期基础(减少)指定(天数)的日期:" + minusLocalDate); System.out.println("-------------------------------------------------" ); } public static void checkLeapYear () { LocalDate localDate = LocalDate.now(); boolean isLeapYear = localDate.isLeapYear(); System.out.println(isLeapYear ? "今年是闰年" : "今年不是闰年" ); System.out.println("-----------------------------------" ); } public static void main (String[] args) { localDateTransition(); localDateCompare(); localDateCalculation(); checkLeapYear(); } }
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ------------------------------------------------- 在默认时区中从系统时钟获取当前日期:2020-07-06 使用指定的格式化程序格式化此日期:2020/07/06 根据设置年、月、日参数获取日期实例:2020-06-18 指定年和年中的天数参数获取日期实例:2020-04-09 通过纪元时(天)获取日期实例:1970-01-11 ------------------------------------------------- ------------------------------------------------- 比较 LocalDate 对象的差值:1 检查此日期是否在指定的日期之后:true 检查此日期是否在指定的日期之前:false ------------------------------------------------- ------------------------------------------------- 获取在当前日期基础(增加)指定(天数)的日期:2020-07-16 获取在当前日期基础(减少)指定(天数)的日期:2020-06-26 ------------------------------------------------- ------------------------------------------------- 今年是闰年 -------------------------------------------------
5、LocalTime 表示时间,通常由”时”、”分”、”秒”组成,该类封装了很多操作时间的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 import java.time.LocalTime;import java.time.format.DateTimeFormatter;public class LocalTimeExample { public static void localTimeTransition () { LocalTime localTime = LocalTime.now(); String formatLocalTime = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss" )); LocalTime hmLocalTime = LocalTime.of(12 , 30 ); LocalTime hmsLocalTime = LocalTime.of(12 , 30 , 20 ); LocalTime hmsnLocalTime = LocalTime.of(12 , 30 , 20 , 10000 ); LocalTime secondOfDayLocalTime = LocalTime.ofSecondOfDay(3600 ); System.out.println("在默认时区中从系统时钟获取当前时间:" + localTime); System.out.println("使用指定的格式化程序格式化此时间:" + formatLocalTime); System.out.println("指定时、分参数获取时间实例:" + hmLocalTime); System.out.println("指定时、分、秒参数获取时间实例:" + hmsLocalTime); System.out.println("指定时、分、秒、纳秒参数获取时间实例:" + hmsnLocalTime); System.out.println("指定秒参数获取时间实例:" + secondOfDayLocalTime); System.out.println("-------------------------------------------------" ); } public static void localTimeCompare () { LocalTime localTime1 = LocalTime.of(12 , 30 ); LocalTime localTime2 = LocalTime.of(12 , 25 ); int difference = localTime1.compareTo(localTime2); boolean isAfter = localTime1.isAfter(localTime2); boolean isBefore = localTime1.isBefore(localTime2); System.out.println("比较 LocalTime 对象的差值:" + difference); System.out.println("检查此时间是否在指定的时间之后:" + isAfter); System.out.println("检查此时间是否在指定的时间之前:" + isBefore); System.out.println("-------------------------------------------------" ); } public static void localTimeCalculation () { LocalTime localTime = LocalTime.now(); LocalTime plusSecondsLocalTime = localTime.plusSeconds(10 ); LocalTime plusMinutesLocalTime = localTime.plusMinutes(10 ); LocalTime plusHoursLocalTime = localTime.plusHours(10 ); LocalTime minusSecondsLocalTime = localTime.minusSeconds(10 ); LocalTime minusMinutesLocalTime = localTime.minusMinutes(10 ); LocalTime minusHoursLocalTime = localTime.minusHours(10 ); System.out.println("获取在当前时间基础(增加)指定(秒)的时间:" + plusSecondsLocalTime); System.out.println("获取在当前时间基础(增加)指定(分钟)的时间:" + plusMinutesLocalTime); System.out.println("获取在当前时间基础(增加)指定(小时)的时间:" + plusHoursLocalTime); System.out.println("获取在当前时间基础(减少)指定(秒)的时间:" + minusSecondsLocalTime); System.out.println("获取在当前时间基础(减少)指定(分钟)的时间:" + minusMinutesLocalTime); System.out.println("获取在当前时间基础(减少)指定(小时)的时间:" + minusHoursLocalTime); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { localTimeTransition(); localTimeCompare(); localTimeCalculation(); } }
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 -------------------------------------------------------- 在默认时区中从系统时钟获取当前时间:23:14:11.746 使用指定的格式化程序格式化此时间:11:14:11 指定时、分参数获取时间实例:12:30 指定时、分、秒参数获取时间实例:12:30:20 指定时、分、秒、纳秒参数获取时间实例:12:30:20.000010 指定秒参数获取时间实例:01:00 -------------------------------------------------------- -------------------------------------------------------- 比较 LocalTime 对象的差值:1 检查此时间是否在指定的时间之后:true 检查此时间是否在指定的时间之前:false -------------------------------------------------------- -------------------------------------------------------- 获取在当前时间基础(增加)指定(秒)的时间:23:14:21.759 获取在当前时间基础(增加)指定(分钟)的时间:23:24:11.759 获取在当前时间基础(增加)指定(小时)的时间:09:14:11.759 获取在当前时间基础(减少)指定(秒)的时间:23:14:01.759 获取在当前时间基础(减少)指定(分钟)的时间:23:04:11.759 获取在当前时间基础(减少)指定(小时)的时间:13:14:11.759 --------------------------------------------------------
6、LocalDateTime 表示日期时间,只不过该类不记录时区信息,是”时间”与”日期”的组合,该类封装了很多操作时间日期的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 1import java.time.*; 2import java.time.format.DateTimeFormatter; 3import java.time.temporal.ChronoField; 4import java.time.temporal.ChronoUnit; 5import java.time.temporal.ValueRange; 6import java.util.Date; 7 8public class LocalDateTimeExample { 9 public static void localDateTimeTransition () { LocalDateTime localDateTime = LocalDateTime.now(); LocalDateTime localDateTimeZone = LocalDateTime.now(ZoneId.of("+08:00" )); int dayOfYear = localDateTime.getDayOfYear(); int dayOfMonth = localDateTime.getDayOfMonth(); DayOfWeek dayOfWeek = localDateTime.getDayOfWeek(); int year = localDateTime.getYear(); Month month = localDateTime.getMonth(); int hour = localDateTime.getHour(); int minute = localDateTime.getMinute(); int second = localDateTime.getSecond(); int nano = localDateTime.getNano(); String formatLocalDateTimeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" )); LocalDateTime fromatLocalDateTime = LocalDateTime.parse("2020-09-18 10:30:50" ,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" )); LocalDateTime ymdhmLocalDateTime = LocalDateTime.of(2020 , 6 , 18 , 12 , 30 ); LocalDateTime ymdhmsLocalDateTime = LocalDateTime.of(2020 , 6 , 18 , 12 , 30 , 20 ); LocalDateTime epochSecondLocalDateTime = LocalDateTime.ofEpochSecond(30 * 366 * 24 * 60 * 60 , 0 , ZoneOffset.UTC); System.out.println("在默认时区中从系统时钟获取当前时间日期:" + localDateTime); System.out.println("在指定时区中从系统时钟获取当前时间日期:" + localDateTimeZone); System.out.println("获取该日期时间是属于该(年)的第几天:" + dayOfYear); System.out.println("获取该日期时间是属于该(月)的第几天:" + dayOfMonth); System.out.println("获取该日期时间是属于该(周)信息,名:" + dayOfWeek.name() + "天值" + dayOfWeek.getValue()); System.out.println("从时间日期中获取(年)信息:" + year); System.out.println("从时间日期中获取(月份)信息,名:" + month.name() + "月份值" + month.getValue()); System.out.println("从时间日期中获取(小时)信息:" + hour); System.out.println("从时间日期中获取(分钟)信息:" + minute); System.out.println("从时间日期中获取(秒)信息:" + second); System.out.println("从时间日期中获取(纳秒)信息:" + nano); System.out.println("在默认时区中从系统时钟获取当前日期时间:" + localDateTime); System.out.println("使用指定的格式化程序格式化时间日期:" + formatLocalDateTimeStr); System.out.println("使用制度的格式格式化字符串到时间日期:" + fromatLocalDateTime); System.out.println("指定年、月、日、时、分参数获取日期时间实例:" + ymdhmLocalDateTime); System.out.println("指定年、月、日、时、分、秒参数获取日期时间实例:" + ymdhmsLocalDateTime); System.out.println("指定使用纪元时(秒)参数获取时间实例:" + epochSecondLocalDateTime); System.out.println("-------------------------------------------------" ); } public static void localDateTimeCompare () { LocalDateTime localDateTime1 = LocalDateTime.of(2020 ,6 ,18 ,11 , 30 ); LocalDateTime localDateTime2 = LocalDateTime.of(2020 ,6 ,18 ,12 , 30 ); int difference = localDateTime1.compareTo(localDateTime2); boolean isAfter = localDateTime1.isAfter(localDateTime2); boolean isBefore = localDateTime1.isBefore(localDateTime2); long until = localDateTime1.until(localDateTime2, ChronoUnit.SECONDS); System.out.println("比较 LocaDatelTime 对象的差值:" + difference); System.out.println("检查此日期时间是否在指定的时间之后:" + isAfter); System.out.println("检查此日期时间是否在指定的时间之前:" + isBefore); System.out.println("以指定单位计算直到另一个日期时间的时间量并指定时间单位:" + until); System.out.println("-------------------------------------------------" ); } public static void localDateTimeCalculation () { LocalDateTime localDateTime = LocalDateTime.now(); LocalDateTime plusSecondsLocalDateTime = localDateTime.plusSeconds(30 ); LocalDateTime plusMinutesLocalDateTime = localDateTime.plusMinutes(10 ); LocalDateTime plusHoursLocalDateTime = localDateTime.plusHours(10 ); LocalDateTime plusDaysLocalDateTime = localDateTime.plusDays(10 ); LocalDateTime plusWeeksLocalTime = localDateTime.plusWeeks(1 ); LocalDateTime plusYearsLocalTime = localDateTime.plusYears(1 ); LocalDateTime minusSecondsLocalDateTime = localDateTime.minusSeconds(30 ); LocalDateTime minusMinutesLocalTime = localDateTime.minusMinutes(30 ); LocalDateTime minusHoursLocalTime = localDateTime.minusHours(10 ); LocalDateTime minusDaysLocalTime = localDateTime.minusDays(10 ); LocalDateTime minusWeeksLocalTime = localDateTime.minusWeeks(1 ); LocalDateTime minusYearsLocalTime = localDateTime.minusYears(1 ); System.out.println("获取在当前日期时间基础(增加)指定(秒)的日期时间:" + plusSecondsLocalDateTime); System.out.println("获取在当前日期时间基础(增加)指定(分钟)的日期时间:" + plusMinutesLocalDateTime); System.out.println("获取在当前日期时间基础(增加)指定(小时)的日期时间:" + plusHoursLocalDateTime); System.out.println("获取在当前日期时间基础(增加)指定(天)的日期时间:" + plusDaysLocalDateTime); System.out.println("获取在当前日期时间基础(增加)指定(周)的日期时间:" + plusWeeksLocalTime); System.out.println("获取在当前日期时间基础(增加)指定(年)的日期时间:" + plusYearsLocalTime); System.out.println("获取在当前日期时间基础(减少)指定(秒)的日期时间:" + minusSecondsLocalDateTime); System.out.println("获取在当前日期时间基础(减少)指定(分钟)的日期时间:" + minusMinutesLocalTime); System.out.println("获取在当前日期时间基础(减少)指定(小时)的日期时间:" + minusHoursLocalTime); System.out.println("获取在当前日期时间基础(减少)指定(天)的日期时间:" + minusDaysLocalTime); System.out.println("获取在当前日期时间基础(减少)指定(周)的日期时间:" + minusWeeksLocalTime); System.out.println("获取在当前日期时间基础(减少)指定(年)的日期时间:" + minusYearsLocalTime); System.out.println("-------------------------------------------------" ); } public static void instantToLocalDateTime () { Instant instant = Instant.now(); LocalDateTime zoneLocalDateTime = LocalDateTime.ofInstant(instant,ZoneId.of("UTC" )); Instant localDateTaimeToInstant = zoneLocalDateTime.toInstant(ZoneOffset.UTC); System.out.println("将 Instant 对象转换为 LocalDateTime 对象并设置时区:" + zoneLocalDateTime); System.out.println("将 LocalDateTime 对象转换为 Instant:" + localDateTaimeToInstant); System.out.println("-------------------------------------------------" ); } public static void localTime () { LocalDateTime localDateTime = LocalDateTime.now(); ValueRange valueRangeDayOfYear = localDateTime.range(ChronoField.DAY_OF_YEAR); ValueRange valueRangeDayOfWeek = localDateTime.range(ChronoField.DAY_OF_WEEK); System.out.println("获取指定字段的有效值范围,今年天数最大值:" + valueRangeDayOfYear.getMaximum()); System.out.println("获取指定字段的有效值范围,今年天数最小值:" + valueRangeDayOfYear.getMinimum()); System.out.println("获取指定字段的有效值范围,这星期数最大值:" + valueRangeDayOfWeek.getMaximum()); System.out.println("获取指定字段的有效值范围,这星期数最小值:" + valueRangeDayOfWeek.getMinimum()); System.out.println("-------------------------------------------------" ); } public static void localDateTimeAndDate () { Date date1 = new Date (); LocalDateTime localDateTime1 = LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault()); LocalDateTime localDateTime2 = LocalDateTime.now(); Date date2 = Date.from(localDateTime2.atZone(ZoneId.systemDefault()).toInstant()); System.out.println("Date 转换为 LocalDateTime:" + localDateTime1); System.out.println("LocalDateTime转换为Date :" + date2); } public static void main (String[] args) { localDateTimeTransition(); localDateTimeCompare(); localDateTimeCalculation(); instantToLocalDateTime(); localTime(); localDateTimeAndDate(); } }
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ----------------------------------------------------------------------------- 在默认时区中从系统时钟获取当前时间日期:2020-07-06T23:10:32.791 在指定时区中从系统时钟获取当前时间日期:2020-07-06T23:10:32.791 获取该日期时间是属于该(年)的第几天:188 获取该日期时间是属于该(月)的第几天:6 获取该日期时间是属于该(周)信息,名:MONDAY天值1 从时间日期中获取(年)信息:2020 从时间日期中获取(月份)信息,名:JULY月份值7 从时间日期中获取(小时)信息:23 从时间日期中获取(分钟)信息:10 从时间日期中获取(秒)信息:32 从时间日期中获取(纳秒)信息:791000000 在默认时区中从系统时钟获取当前日期时间:2020-07-06T23:10:32.791 使用指定的格式化程序格式化日期时间:2020-07-06 11:10:32 指定年、月、日、时、分参数获取日期时间实例:2020-06-18T12:30 指定年、月、日、时、分、秒参数获取日期时间实例:2020-06-18T12:30:20 指定使用纪元时(秒)参数获取时间实例:2000-01-24T00:00 ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- 比较 LocaDatelTime 对象的差值:-1 检查此日期时间是否在指定的时间之后:false 检查此日期时间是否在指定的时间之前:true 以指定单位计算直到另一个日期时间的时间量并指定时间单位:3600 ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- 获取在当前日期时间基础(增加)指定(秒)的日期时间:2020-07-06T23:11:02.805 获取在当前日期时间基础(增加)指定(分钟)的日期时间:2020-07-06T23:20:32.805 获取在当前日期时间基础(增加)指定(小时)的日期时间:2020-07-07T09:10:32.805 获取在当前日期时间基础(增加)指定(天)的日期时间:2020-07-16T23:10:32.805 获取在当前日期时间基础(增加)指定(周)的日期时间:2020-07-13T23:10:32.805 获取在当前日期时间基础(增加)指定(年)的日期时间:2021-07-06T23:10:32.805 获取在当前日期时间基础(减少)指定(秒)的日期时间:2020-07-06T23:10:02.805 获取在当前日期时间基础(减少)指定(分钟)的日期时间:2020-07-06T22:40:32.805 获取在当前日期时间基础(减少)指定(小时)的日期时间:2020-07-06T13:10:32.805 获取在当前日期时间基础(减少)指定(天)的日期时间:2020-06-26T23:10:32.805 获取在当前日期时间基础(减少)指定(周)的日期时间:2020-06-29T23:10:32.805 获取在当前日期时间基础(减少)指定(年)的日期时间:2019-07-06T23:10:32.805 ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- 将 Instant 对象转换为 LocalDateTime 对象并设置时区:2020-07-06T15:10:32.806 将 LocalDateTime 对象转换为 Instant:2020-07-06T15:10:32.806Z ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- 获取指定字段的有效值范围,今年天数最大值:366 获取指定字段的有效值范围,今年天数最小值:1 获取指定字段的有效值范围,这星期数最大值:7 获取指定字段的有效值范围,这星期数最小值:1 ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- Date 转换为 LocalDateTime:2020-07-06T23:10:32.806 LocalDateTime转换为Date :Mon Jul 06 23:10:32 CST 2020 -----------------------------------------------------------------------------
7、ZoneDateTime 该类中的方法基本和 LocalDateTime 一致,不过该类会记录时区信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import java.time.*;public class ZonedDateTimeExample { public static void zoneTimeTransition () { ZonedDateTime zonedDateTime = ZonedDateTime.now(); ZoneId zoneId = zonedDateTime.getZone(); LocalDate localDate = zonedDateTime.toLocalDate(); LocalDateTime localDateTime = zonedDateTime.toLocalDateTime(); OffsetDateTime offsetDateTime = zonedDateTime.toOffsetDateTime(); Instant instant = zonedDateTime.toInstant(); ZonedDateTime zonedDateTimeZone = ZonedDateTime.of(LocalDateTime.now(),ZoneId.of("GMT+8" )); ZonedDateTime ymdhmsnZonedDateTimeZone = ZonedDateTime.of(2020 ,6 ,18 ,12 , 30 ,1 ,0 ,ZoneId.of("GMT+8" )); System.out.println("在默认时区中从系统时钟获取当前日期时间:" + zonedDateTime); System.out.println("获取时区信息:" + zoneId); System.out.println("转换为 LocalDate 对象:" + localDate); System.out.println("转换为 LocalDateTime 对象:" + localDateTime); System.out.println("转换为 OffsetDateTime 对象:" + offsetDateTime); System.out.println("转换为 Instant 对象:" + instant); System.out.println("指定年、月、日、时、分、秒参数获取日期时间实例:" + zonedDateTimeZone); System.out.println("指定年、月、日、时、分、秒参数获取日期时间实例:" + ymdhmsnZonedDateTimeZone); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { zoneTimeTransition(); } }
输出如下:
1 2 3 4 5 6 7 8 9 10 11 ------------------------------------------------------------------------------------------ 在默认时区中从系统时钟获取当前日期时间:2020-07-06T23:10:02.173+08:00[Asia/Shanghai] 获取时区信息:Asia/Shanghai 转换为 LocalDate 对象:2020-07-06 转换为 LocalDateTime 对象:2020-07-06T23:10:02.173 转换为 OffsetDateTime 对象:2020-07-06T23:10:02.173+08:00 转换为 Instant 对象:2020-07-06T15:10:02.173Z 指定年、月、日、时、分、秒参数获取日期时间实例:2020-07-06T23:10:02.173+08:00[GMT+08:00] 指定年、月、日、时、分、秒参数获取日期时间实例:2020-06-18T12:30:01+08:00[GMT+08:00] ------------------------------------------------------------------------------------------
8、Period Period 主要用于获取时间度量值,可以获取两个日期的年、月、日的差值等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.time.LocalDate;import java.time.Period;public class PeriodExample { public static void datePeriod () { LocalDate localDate1 = LocalDate.of(2018 , 6 , 16 ); LocalDate localDate2 = LocalDate.of(2020 , 8 , 18 ); Period period = Period.between(localDate1, localDate2); System.out.println("年差量:" + period.getYears()); System.out.println("月差量:" + period.getMonths()); System.out.println("日差量:" + period.getDays()); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { datePeriod(); } }
输出如下:
1 2 3 4 5 6 ------------ 年差量:2 月差量:2 日差量:2 ------------
9、ZoneId 主要用于创建 ZoneDateTime 时,指定时区选项,这里只介绍下如何创建 ZoneId 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import java.time.OffsetDateTime;import java.time.ZoneId;public class ZoneIdExample { public static void getZoneId () { ZoneId zoneId = ZoneId.systemDefault(); ZoneId zoneIdOf = ZoneId.of("+08:00" ); ZoneId zoneIdOfOffset = ZoneId.ofOffset("GMT" , OffsetDateTime.now().getOffset()); System.out.println("获取系统默认的时区:" + zoneId.getId()); System.out.println("获取此ID的时区规则以执行计算:" + zoneId.getRules()); System.out.println("从时区ID获取 ZoneId 的实例:" + zoneIdOf); System.out.println("从时区ID获取 ZoneId 的实例:" + zoneIdOfOffset); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { getZoneId(); } }
输出如下:
1 2 3 4 5 6 7 ---------------------------------------------------------------------- 获取系统默认的时区:Asia/Shanghai 获取此ID的时区规则以执行计算:ZoneRules[currentStandardOffset=+08:00] 从时区ID获取 ZoneId 的实例:+08:00 从时区ID获取 ZoneId 的实例:GMT+08:00 ----------------------------------------------------------------------
10、ZoneOffset 表示时区偏移量,是 ZoneId 的子类,相对于格林尼治时间(GMT)的时间偏差,只是只处理与格林尼治的时间差;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 import java.time.OffsetDateTime;import java.time.ZoneOffset;import java.time.zone.ZoneRules;public class ZoneOffsetExample { public static void getNowZoneOffset () { ZoneOffset zoneOffsetNow = OffsetDateTime.now().getOffset(); ZoneRules zoneRules = zoneOffsetNow.getRules(); System.out.println("获取当前日期时间的【ZoneOffset】对象:" + zoneOffsetNow); System.out.println("获取此偏移量相关时区的规则:" + zoneRules); System.out.println("-------------------------------------------------" ); } public static void createZoneOffset () { ZoneOffset zoneOffsetOf = ZoneOffset.of("+08:00" ); ZoneOffset zoneOffsetSeconds = ZoneOffset.ofTotalSeconds(28800 ); ZoneOffset zoneOffsetByHours = ZoneOffset.ofHours(8 ); ZoneOffset zoneOffsetByHoursMinites = ZoneOffset.ofHoursMinutes(8 , 30 ); ZoneOffset zoneOffsetByHoursMinutesSeconds = ZoneOffset.ofHoursMinutesSeconds(8 , 30 , 10 ); System.out.println("使用【偏移量ID】获取【ZoneOffset】对象:" + zoneOffsetOf); System.out.println("使用以【秒】为【偏移量ID】获取【ZoneOffset】对象:" + zoneOffsetSeconds); System.out.println("使用以【小时】为【偏移量ID】获取【ZoneOffset】对象:" + zoneOffsetByHours); System.out.println("使用以【小时与分钟】为【偏移量ID】获取【ZoneOffset】对象:" + zoneOffsetByHoursMinites); System.out.println("使用以【小时、分钟和秒】为【偏移量ID】获取【ZoneOffset】对象:" + zoneOffsetByHoursMinutesSeconds); System.out.println("-------------------------------------------------" ); } public static void compareZoneOffset () { ZoneOffset zoneOffsetOf1 = ZoneOffset.of("+08:00" ); ZoneOffset zoneOffsetOf2 = ZoneOffset.of("+09:00" ); int seconds = zoneOffsetOf1.compareTo(zoneOffsetOf2); System.out.println("将此偏移量与另一个偏移量按降序比较:" + seconds); System.out.println("-------------------------------------------------" ); } public static void main (String[] args) { getNowZoneOffset(); createZoneOffset(); compareZoneOffset(); } }
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ------------------------------------------------------------------------ 获取当前日期时间的【ZoneOffset】对象:+08:00 获取此偏移量相关时区的规则:ZoneRules[currentStandardOffset=+08:00] ------------------------------------------------------------------------ ------------------------------------------------------------------------ 使用【偏移量ID】获取【ZoneOffset】对象:+08:00 使用以【秒】为【偏移量ID】获取【ZoneOffset】对象:+08:00 使用以【小时】为【偏移量ID】获取【ZoneOffset】对象:+08:00 使用以【小时与分钟】为【偏移量ID】获取【ZoneOffset】对象:+08:30 使用以【小时、分钟和秒】为【偏移量ID】获取【ZoneOffset】对象:+08:30:10 ------------------------------------------------------------------------ ------------------------------------------------------------------------ 将此偏移量与另一个偏移量按降序比较:3600 ------------------------------------------------------------------------
示例地址: Java 8 新增的日期时间 API 使用示例
转自:http://www.mydlq.club/article/87