目录
一、概述
太阳日的长度是人类测量时间的标准方式。传统上,这被细分为24小时60分60秒,形成86400秒的一天。现代计时是以原子钟为基础的,原子钟精确地定义了相对于铯原子跃迁的SI秒。一秒的长度被定义为非常接近一天的86400分之一。
不幸的是,随着地球自转,一天的长度也不尽相同。此外,随着时间的推移,随着地球速度的减慢,一天的平均长度越来越长。因此,2012年的太阳日长度略长于86400 SI秒。任何一天的实际长度以及地球减速的程度都是无法预测的,
只能通过测量来确定。UT1时间刻度捕捉到一天的准确长度,但仅在一天结束后的某个时间可用。
UTC时间刻度是一种标准方法,用于将UT1中所有额外的一秒分数捆绑成整秒,称为闰秒。根据地球的自转变化,闰秒可以增加或减少。因此,UTC允许一天有86399 SI秒或86401 SI秒(如有必要),以保持一天与太阳对齐。
现代UTC时标于1972年引入,引入了整闰秒的概念。1958年至1972年期间,UTC的定义非常复杂,有微小的亚秒级跳跃和概念秒长度的改变。截至2012年,有关再次更改UTC定义的讨论正在进行中,可能会删除闰秒或引入其他更改。
鉴于上述精确计时的复杂性,这个JavaAPI定义了自己的时间尺度,Java时间尺度。
Java时间刻度将每个日历日精确地划分为86400个细分,称为秒。这些秒数可能与SI秒数不同。Java时间尺度对时间线的不同部分有着略微不同的定义,每个部分都基于作为民用时间基础的一致国际时间尺度。无论何时修改或替换国际商定的时间尺度,都必须为其定义一个新的Java时间尺度段。每个分段必须满足以下要求:
1)java时间尺度应与国际民事时间尺度密切匹配;
2)java时间刻度应与每天中午的国际民用时间刻度完全一致;
3)java时间尺度应与国际民用时间尺度具有精确定义的关系。
截至2013年,Java时间尺度中目前有两个部分。
对于1972-11-03(下文讨论的确切边界)至另行通知的时间段,一致同意的国际时标为UTC(带闰秒)。在此段中,Java时间刻度与UTC-SLS相同。在没有闰秒的日子,这与UTC相同。在有闰秒的日子里,闰秒平均分布在一天中的最后1000秒,保持每天86400秒的外观。
对于1972-11-03年之前任意向后延伸的段,一致国际时间标度定义为UT1,先入为主,相当于本初子午线(格林威治)上的(平均)太阳时间。在这一部分中,Java时间尺度与共识国际时间尺度相同。两段之间的精确边界是UT1=UTC在1972-11-03T00:00和1972-11-04T12:00之间的瞬间。
使用JSR-310 API的Java时间尺度的实现不需要提供任何亚秒级的精确时钟,也不需要单调或平滑地进行。因此,实际执行UTC-SLS转换或以其他方式了解闰秒不需要实施。
java时间日期类从jdk1.0开始一直在更新,jdk8版本做了很大的改动,jdk8之前,使用Date,Calendar,SimpleDateFormater处理时间。jdk8则提供了Instant, LocalDate, LocalTime, LocalDatetime, Duration ,Period,ZonedDateTime等时间类,以及不变线程安全类DateTimeFormatter做日期时间格式化解析操作,极大丰富了java的日期时间库。
二、Instant
它是时间线上的瞬时点,时区相关。
此类为时间线上的单个瞬时点建模。这可能用于记录应用程序中的事件时间戳。
瞬时的存储范围需要大于长整形long。为了实现这一点,Instant类存储一个表示历元秒seconds的长整数long和一个表示纳秒nanos的整数int,该整数始终在0和999999999之间。该历元秒是以1970-01-01T00:00:00Z的Java历元标准为准则的,因此,历元后的瞬间seconds为正值,之前的瞬间seconds为负值。对于历元秒seconds和纳秒nanos部分,值越大,时间越晚。
它是不可变类和线程安全的。
// 获取当前UTC时间
Instant now = Instant.now();
// 根据时间偏移量获取时间
Instant instant = Instant.ofEpochSecond(1);
// 获取当前UTC+8时间
Instant instant1 = Instant.now(Clock.system(ZoneId.of("UTC+8")));
// 判断instant时间前后
boolean before = instant.isBefore(now);
boolean after = instant1.isAfter(instant);
//加一天
Instant plus = instant.plus(1, ChronoUnit.DAYS);
// 获取epochSecond
long epochSecond = instant.getEpochSecond();
// 获取nano
int nano = instant.getNano();
// 获取epoch millSecond
long l = instant.toEpochMilli();
// 减一秒
Instant instant2 = instant.minusMillis(1);
// 与LocalDateTime转换
LocalDateTime time = LocalDateTime.ofInstant(instant, ZoneId.ofOffset("", ZoneOffset.UTC);
LocalDateTime date = LocalDateTime.of(1, 1, 1, 0, 0);
Instant instant3 = date.toInstant(ZoneOffset.UTC);
三、LocalDate
LocalDate是一个不可变的日期时间对象,它表示一个日期,通常被视为年-月-日。还可以访问其他日期字段,例如年中的日期、周中的日期和年中的周。例如,值“2007年10月2日”可以存储在LocalDate中。
LocalDate类不存储或表示时间或时区,与时区无关。相反,它是对日期的描述,例如生日。如果没有诸如偏移量或时区之类的附加信息,它不能表示时间线上的某个瞬间。
// 获取当前localDate, 系统当前默认时区
LocalDate now = LocalDate.now();
LocalDate now1 = LocalDate.now(ZoneId.systemDefault());
// 获取UTC当前localDate
LocalDate now2 = LocalDate.now(Clock.systemUTC());
// 指定年月日
LocalDate localDate = LocalDate.of(1991, 1, 1);
// 获取年月日
int year = localDate.getYear();
int monthValue = localDate.getMonthValue();
int dayOfMonth = localDate.getDayOfMonth();
// 获取星期几
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
// 获取一年第几天
int dayOfYear = localDate.getDayOfYear();
// 比较
boolean before = localDate.isBefore(now);
boolean after = localDate.isAfter(now);
// 是否瑞年
boolean leapYear = localDate.isLeapYear();
// 减偏移时间
LocalDate localDate1 = localDate.minusDays(1);
LocalDate localDate2 = localDate.minusMonths(1);
LocalDate localDate3 = localDate.minusYears(1);
//加偏移时间
LocalDate localDate4 = localDate.plusDays(1);
LocalDate localDate5 = localDate.plusMonths(1);
LocalDate localDate6 = localDate.plusWeeks(1);
// 与LocalDateTime转换
LocalDateTime localDateTime = localDate.atTime(0, 0);
LocalDate toLocalDate = localDateTime.toLocalDate();
四、LocalTime
ISO-8601日历系统中没有时区的时间,如10:15:30。
LocalTime是一个不可变的日期-时间对象,它表示一个时间,通常被视为小时-分钟-秒。时间表示为纳秒精度。例如,值“13:45.30.123456789”可以存储在LocalTime中。
LocalTime类不存储或表示日期或时区,与时区无关。相反,它是一个描述当地时间的挂钟。如果没有诸如偏移量或时区之类的附加信息,它不能表示时间线上的某个瞬间。
LocalTime是不可变的线程安全类。
// 获取当前LocalTime, 系统当前默认时区
LocalTime now = LocalTime.now();
LocalTime now1 = LocalTime.now(ZoneId.systemDefault());
// 获取UTC当前LocalTime
LocalTime now2 = LocalTime.now(Clock.systemUTC());
// 指定时分秒纳秒
LocalTime localTime = LocalTime.of(12, 30, 15, 0);
// 获取时分秒纳秒
int hour = localTime.getHour();
int minute = localTime.getMinute();
int second = localTime.getSecond();
int nano = localTime.getNano();
// 比较
boolean before = localTime.isBefore(now);
boolean after = localTime.isAfter(now);
// 减偏移时间
LocalTime localTime1 = localTime.minusHours(1);
LocalTime localTime2 = localTime.minusMinutes(1);
LocalTime localTime3 = localTime.minusSeconds(1);
LocalTime localTime4 = localTime.minusNanos(1);
//加偏移时间
LocalTime localTime5 = localTime.plusHours(1);
LocalTime localTime6 = localTime.plusMinutes(1);
LocalTime localTime7 = localTime.plusSeconds(1);
LocalTime localTime8 = localTime.plusNanos(1);
// 与LocalDateTime转换
LocalDateTime localDateTime = localTime.atDate(LocalDate.now());
LocalTime toLocalDate = localDateTime.toLocalTime();
五、LocalDateTime
ISO-8601日历系统中没有时区的日期时间,例如2007-12-03T10:15:30。
LocalDateTime是一个不可变的日期时间对象,它表示一个日期时间,通常被视为年-月-日-小时-分-秒。还可以访问其他日期和时间字段,例如年中的日期、周中的日期和周。时间表示为纳秒精度。例如,值“2007年10月2日13:45.30.123456789”可以存储在LocalDateTime中。
LocalDateTime类不存储或表示时区,与时区无关。相反,它是对日期的描述,例如生日,与挂钟上显示的当地时间相结合。一样的,如果没有诸如偏移量或时区之类的附加信息,它不能表示时间线上的某个瞬间。
LocalDateTime是不可变的线程安全类。
// 获取当前LocalDateTime, 系统当前默认时区
LocalDateTime now = LocalDateTime.now();
LocalDateTime now1 = LocalDateTime.now(ZoneId.systemDefault());
// 获取UTC当前LocalTime
LocalDateTime now2 = LocalDateTime.now(Clock.systemUTC());
// 指定年月日时分秒
LocalDateTime localDateTime = LocalDateTime.of(1990, 12, 1, 12, 0, 0);
// 指定LocalDate与LocalTime
LocalDateTime localDateTime1 = LocalDateTime.of(LocalDate.now(), LocalTime.now());
// 获取年月日时分秒纳秒
int year = localDateTime.getYear();
Month month = localDateTime.getMonth();
int dayOfYear = localDateTime.getDayOfYear();
int hour = localDateTime.getHour();
int minute = localDateTime.getMinute();
int second = localDateTime.getSecond();
int nano = localDateTime.getNano();
// 比较
boolean before = localDateTime.isBefore(now);
boolean after = localDateTime.isAfter(now);
// 减偏移时间
LocalDateTime localTime1 = localDateTime.minusHours(1);
LocalDateTime localTime2 = localDateTime.minusMinutes(1);
LocalDateTime localTime3 = localDateTime.minusYears(1);
LocalDateTime localTime4 = localDateTime.minusWeeks(1);
//加偏移时间
LocalDateTime localTime5 = localDateTime.plusHours(1);
LocalDateTime localTime6 = localDateTime.plusMinutes(1);
LocalDateTime localTime7 = localDateTime.plusSeconds(1);
LocalDateTime localTime8 = localDateTime.plusNanos(1);
// 与LocalDate和LocalTime转换
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();
//与Instant转换
Instant instant = localDateTime.toInstant(ZoneOffset.UTC);
LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
//与ZoneDateTime转换
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneOffset.UTC);
LocalDateTime localDateTime2 = zonedDateTime.toLocalDateTime();
// 与OffsetDateTime转换
OffsetDateTime offsetDateTime = localDateTime.atOffset(ZoneOffset.UTC);
LocalDateTime localDateTime3 = offsetDateTime.toLocalDateTime();