instant
Instant用于表示一个时间戳,它与我们常使用的System.currentTimeMillis()有些类似,不过Instant可以精确到纳秒(Nano-Second),System.currentTimeMillis()方法只精确到毫秒(Milli-Second)。如果查看Instant源码,发现它的内部使用了两个常量,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999,999,999)。
Instant除了使用now()方法创建外,还可以通过ofEpochSecond方法创建:
Instant instant = Instant.ofEpochSecond(120, 100000);
ofEpochSecond()方法的第一个参数为秒,第二个参数为纳秒,上面的代码表示从1970-01-01 00:00:00开始后两分钟的10万纳秒的时刻,控制台上的输出为:
1970-01-01T00:02:00.000100Z
Duration
Duration的内部实现与Instant类似,也是包含两部分:seconds表示秒,nanos表示纳秒。两者的区别是Instant用于表示一个时间戳(或者说是一个时间点),而Duration表示一个时间段,所以Duration类中不包含**now()**静态方法。可以通过Duration.between()方法创建Duration对象:
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(); // 这段时间的纳秒数
Duration对象还可以通过of()方法创建,该方法接受一个时间段长度,和一个时间单位作为参数:
Duration duration1 = Duration.of(5, ChronoUnit.DAYS); // 5天
Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS); // 1000毫秒
Period
Period在概念上和Duration类似,区别在于Period是以年月日来衡量一个时间段,比如2年3个月6天:
Period period = Period.of(2, 3, 6);
Period对象也可以通过between()方法创建,值得注意的是,由于Period是以年月日衡量时间段,所以**between()**方法只能接收LocalDate类型的参数:
Period period = Period.between(
LocalDate.of(2017,01,1),
LocalDate.of(2017, 06, 15));
System.out.println("相距年份:"+period.getYears()+"相距月份:"+period.getMonths()+"相距日期:"+period.getDays());
相距年份:0相距月份:5相距日期:14
但要注意的是,Period 计算天数差是计算一个月之内的天数差而不是两个日期之间实际相隔的天数差。
public void test3() {
LocalDate now = LocalDate.of(2021, 12, 2);
LocalDate end = LocalDate.of(2022, 1, 8);
Period between = Period.between(now, end);
System.out.println("Period 计算两个时间的差: " + between.getYears() + "年, " + between.getMonths() + "月, " + between.getDays()+"日");
}
输出结果为:
Period 计算两个时间的差:0年, 1月, 6日
LocalDate/LocalTime/LocalDateTime使用
LocalDate类表示一个具体的日期,但不包含具体时间,也不包含时区信息。可以通过LocalDate的静态方法of()创建一个实例, LocalDate也包含一些方法用来获取年份,月份,天,星期几等:
LocalDate localDate = LocalDate.of(2017, 1, 4); // 初始化一个日期:2017-01-04
int year = localDate.getYear(); // 年份:2017
Month month = localDate.getMonth(); // 月份:JANUARY
int dayOfMonth = localDate.getDayOfMonth(); // 月份中的第几天:4
DayOfWeek dayOfWeek = localDate.getDayOfWeek(); // 一周的第几天:WEDNESDAY
int length = localDate.lengthOfMonth(); // 月份的天数:31
boolean leapYear = localDate.isLeapYear(); // 是否为闰年:false
也可以调用静态方法now()来获取当前日期:
LocalDate now = LocalDate.now();
LocalTime和LocalDate类似,他们之间的区别在于LocalDate不包含具体时间,而LocalTime包含具体时间,例如:
LocalTime localTime = LocalTime.of(17, 23, 52); // 初始化一个时间:17:23:52
int hour = localTime.getHour(); // 时:17
int minute = localTime.getMinute(); // 分:23
int second = localTime.getSecond(); // 秒:52
LocalDateTime类是LocalDate和LocalTime的结合体,可以通过of()方法直接创建,也可以调用LocalDate的atTime()方法或LocalTime的atDate()方法将LocalDate或LocalTime合并成一个LocalDateTime:
LocalDateTime ldt1 = LocalDateTime.of(2017, Month.JANUARY, 4, 17, 23, 52);
LocalDate localDate = LocalDate.of(2017, Month.JANUARY, 4);
LocalTime localTime = LocalTime.of(17, 23, 52);
LocalDateTime ldt2 = localDate.atTime(localTime);
LocalDateTime也提供用于向LocalDate和LocalTime的转化:
LocalDate date = ldt1.toLocalDate();
LocalTime time = ldt1.toLocalTime();
字符串转时间(DateTimeFormatter线程安全的)
String date="2019年10月01日";
DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy年MM月dd日");
LocalDate localDate=LocalDate.parse(date,dateTimeFormatter);
时间转字符串
DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy-MM-dd");
System.out.println(LocalDateTime.now().format(dateTimeFormatter));
将LocalDateTime转为时间戳
long i=LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
将13位时间戳转为日期
LocalDateTime localDateTime=LocalDateTime.ofEpochSecond((long)l/1000,0, ZoneOffset.of("+8"));
时区
Java 8中的时区操作被很大程度上简化了,新的时区类java.time.ZoneId是原有的java.util.TimeZone类的替代品。ZoneId对象可以通过ZoneId.of()方法创建,也可以通过ZoneId.systemDefault()获取系统默认时区:
ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
ZoneId systemZoneId = ZoneId.systemDefault();
of()方法接收一个“区域/城市”的字符串作为参数,你可以通过getAvailableZoneIds()方法获取所有合法的“区域/城市”字符串:
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
对于老的时区类TimeZone,Java 8也提供了转化方法:
ZoneId oldToNewZoneId = TimeZone.getDefault().toZoneId();
有了ZoneId,我们就可以将一个LocalDate、LocalTime或LocalDateTime对象转化为ZonedDateTime对象:
LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, shanghaiZoneId);
将zonedDateTime打印到控制台为:
2017-01-05T15:26:56.147+08:00[Asia/Shanghai]
ZonedDateTime对象由两部分构成,LocalDateTime和ZoneId,其中2017-01-05T15:26:56.147部分为LocalDateTime,+08:00[Asia/Shanghai]部分为ZoneId。
另一种表示时区的方式是使用ZoneOffset,它是以当前时间和世界标准时间(UTC)/格林威治时间(GMT)的偏差来计算,例如:
ZoneOffset zoneOffset = ZoneOffset.of("+09:00");
LocalDateTime localDateTime = LocalDateTime.now();
OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, zoneOffset);
ChronoUtil
测量时间的单位,如果要测量单位时间内的日期,通过ChronoUtil.between获取,例如返回两个时间之间的天数,使用如下:
long value= ChronoUnit.DAYS.between(LocalDate.of(1997,04,07),LocalDate.of(2019,07,19));
附 LocalDateTime方法:
adjustInto调整指定的Temporal和当前LocalDateTime对atOffset结合LocalDateTime和ZoneOffset创建一个atZone结合LocalDateTime和指定时区创建一个ZonedDcompareTo比较两个LocalDateTimeformat格式化LocalDateTime生成一个字符串from转换TemporalAccessor为LocalDateTiget得到LocalDateTime的指定字段的值getDayOfMonth得到LocalDateTime是月的第几天getDayOfWeek得到LocalDateTime是星期几getDayOfYear得到LocalDateTime是年的第几天getHour得到LocalDateTime的小时getLong得到LocalDateTime指定字段的值getMinute得到LocalDateTime的分钟getMonth得到LocalDateTime的月份getMonthValue得到LocalDateTime的月份,从1到12getNano得到LocalDateTime的纳秒数getSecond得到LocalDateTime的秒数getYear得到LocalDateTime的年份isAfter判断LocalDateTime是否在指定LocalDateTisBefore判断LocalDateTime是否在指定LocalDateTisEqual判断两个LocalDateTime是否相等isSupported判断LocalDateTime是否支持指定时间字段或单元minus返回LocalDateTime减去指定数量的时间得到的值minusDays返回LocalDateTime减去指定天数得到的值minusHours返回LocalDateTime减去指定小时数得到的值minusMinutes返回LocalDateTime减去指定分钟数得到的值minusMonths返回LocalDateTime减去指定月数得到的值minusNanos返回LocalDateTime减去指定纳秒数得到的值minusSeconds返回LocalDateTime减去指定秒数得到的值minusWeeks返回LocalDateTime减去指定星期数得到的值minusYears返回LocalDateTime减去指定年数得到的值now返回指定时钟的当前LocalDateTimeof根据年、月、日、时、分、秒、纳秒等创建LocalDateTiofEpochSecond根据秒数(从1970-01-0100:00:00开始)创建LofInstant根据Instant和ZoneId创建LocalDateTimparse解析字符串得到LocalDateTimeplus返回LocalDateTime加上指定数量的时间得到的值plusDays返回LocalDateTime加上指定天数得到的值plusHours返回LocalDateTime加上指定小时数得到的值plusMinutes返回LocalDateTime加上指定分钟数得到的值plusMonths返回LocalDateTime加上指定月数得到的值plusNanos返回LocalDateTime加上指定纳秒数得到的值plusSeconds返回LocalDateTime加上指定秒数得到的值plusWeeks返回LocalDateTime加上指定星期数得到的值plusYears返回LocalDateTime加上指定年数得到的值query查询LocalDateTimerange返回指定时间字段的范围toLocalDate返回LocalDateTime的LocalDate部分toLocalTime返回LocalDateTime的LocalTime部分toString返回LocalDateTime的字符串表示truncatedTo返回LocalDateTime截取到指定时间单位的拷贝until计算LocalDateTime和另一个LocalDateTiwith返回LocalDateTime指定字段更改为新值后的拷贝withDayOfMonth返回LocalDateTime月的第几天更改为新值后的拷贝withDayOfYear返回LocalDateTime年的第几天更改为新值后的拷贝withHour返回LocalDateTime的小时数更改为新值后的拷贝withMinute返回LocalDateTime的分钟数更改为新值后的拷贝withMonth返回LocalDateTime的月份更改为新值后的拷贝withNano返回LocalDateTime的纳秒数更改为新值后的拷贝withSecond返回LocalDateTime的秒数更改为新值后的拷贝withYear返回LocalDateTime年份更改为新值后的拷贝
