实现了JSR-310规范的新的日期时间的API位于java.time包及子包下。
无特殊说明这些类都是不可变的和线程安全的。
常用的日期时间类
Clock
抽象类,使用时区提供对当前即时,日期和时间的访问的时钟。
该类的实例用于查找当前时刻,可以使用存储的时区来解释当前时刻(当前时间戳转成时区时间的表示)。
Clock有四个内部子类,这些子类只有包内可见。
FixedClock始终返回同一时刻,常用于测试。
OffsetClock为基础时钟添加偏移量,构造方法第一个参数为基础时钟,第二个参数为Duration的偏移量。
TickClock为基础时钟添加偏移量,构造方法第一个参数为基础时钟,第二个参数为long型的纳秒偏移量。
SystemClock调用System.currentTimeMillis()返回最新时间。
@Test
public void test(){
//UTC时间戳
System.out.println(Clock.systemUTC().millis());
//当前时区时间戳
System.out.println(Clock.systemDefaultZone().millis());
//当前时间戳+1小时
System.out.println(Clock.offset(Clock.systemDefaultZone(), Duration.of(1, ChronoUnit.HOURS)).millis());
}
Duration
代表一段时间。
该类以秒和纳秒为单位建立数量或时间量。 它可以使用其他基于持续时间的单位进行访问,例如毫秒、秒、分钟、小时和天。天被视为完全等于24小时。
一般用于小时间单位的一段时间,Period常用于大时间单位。
@Test
public void test(){
//获取秒数
System.out.println(Duration.ofDays(1).getSeconds());
System.out.println(Duration.ofHours(1).getSeconds());
System.out.println(Duration.ofMinutes(1).getSeconds());
//获取纳秒数
System.out.println(Duration.ofMillis(1).getNano());
System.out.println(Duration.ofNanos(1).getNano());
//两个时间的差值
System.out.println(Duration.between(LocalDateTime.now(),
LocalDateTime.parse("2022-12-12 12:12:12",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
.getSeconds());
//1天+1小时
System.out.println(Duration.ofDays(1)
.plus(Duration.ofHours(1)).getSeconds());
//1天-1小时
System.out.println(Duration.ofDays(1)
.minus(Duration.ofHours(1)).getSeconds());
}
Instant
时刻,是时间线上的瞬间点。
该类在时间线上建立单个瞬时点。 这可能用于在程序中记录事件时间戳。
实际上,这一瞬间存在一些限制。 可测量的时间线受限于
long的大小,
这大于当前估计的宇宙年龄, 该瞬间单位为纳秒。瞬间的范围需要存储大于
long
。 为了实现这一点,类存储一个long
表示纪元秒和一个int
表示纳秒,这将始终为0和999,999,999之间。 纪元秒数是从标准的Java纪元1970-01-01T00:00:00Z
开始测量,其中纪元之后的时刻具有正值,较早的时刻具有负值。
@Test
public void test(){
//纪元开始的时刻
System.out.println(Instant.EPOCH);
//获取UTC时间的纪元秒数
System.out.println(Instant.now().getEpochSecond());
//是否支持给定的时间单位
System.out.println(Instant.now().isSupported(ChronoUnit.HOURS));
//UTC+8,东八区的当前时刻
System.out.println(Instant.now().atOffset(ZoneOffset.of("+8")));
//+12小时的时刻
System.out.println(Instant.now().plus(12,ChronoUnit.HOURS));
//-12小时的时刻
System.out.println(Instant.now().minus(12,ChronoUnit.HOURS));
//比较两个时刻的先后
System.out.println(Instant.now().
isAfter(LocalDateTime.now().toInstant(ZoneOffset.of("+8"))));
}
LocalDate
LocalDate
是一个不可变的日期时间对象,表示日期,通常被视为年月日,也可以获取其他信息,例如日期,星期几和星期。该类不存储或表示时间或时区,它是日期的描述,它不能代表时间线上的即时信息,没有偏移或时区。
@Test
public void test(){
// 2022-10-12是星期几
System.out.println(LocalDate.of(2022, 10, 12).getDayOfWeek());
//当前日期
System.out.println(LocalDate.now());
//获取纪元,CE是公元 BCE是公元前
System.out.println(LocalDate.now().getEra());
//是否闰年
System.out.println(LocalDate.now().isLeapYear());
//+3周
System.out.println(LocalDate.now().plus(3,ChronoUnit.WEEKS));
//-3个月
System.out.println(LocalDate.now().minus(3,ChronoUnit.MONTHS));
}
LocalDateTime
LocalDateTime
是一个不可变的日期时间对象,代表日期时间,通常被视为年 - 月 - 日 - 时 - 分 - 秒。 也可以获取日期,星期几和星期。 时间表示为纳秒精度。该类不存储或表示时区。 相反,它是对日期的描述。它不能代表时间线上的即时信息,没有偏移或时区。
@Test
public void test(){
//当前日期时间
System.out.println(LocalDateTime.now());
//用给定的日期时间格式化器 格式化 当前日期时间
System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")));
//获取日期
System.out.println(LocalDateTime.now().toLocalDate());
//获取时间
System.out.println(LocalDateTime.now().toLocalTime());
//当前日期时间是否在给定日期时间之后
System.out.println(LocalDateTime.now()
.isAfter(LocalDateTime
.of(2022, 10, 12,16,20,55)));
//当前日期时间是否在给定日期时间之前
System.out.println(LocalDateTime.now()
.isBefore(LocalDateTime
.of(2022, 10, 12,16,20,55)));
//+3小时
System.out.println(LocalDateTime.now().plus(3,ChronoUnit.HOURS));
//-3秒
System.out.println(LocalDateTime.now().minus(3,ChronoUnit.SECONDS));
}
LocalTime
LocalTime
是一个不可变的日期时间对象,代表一个时间,通常表示小时 - 分钟 - 秒。 时间表示为纳秒精度。该类不存储或表示时区。它是对日期的描述。它不能代表时间线上的即时信息,没有偏移或时区。
@Test
public void test(){
//当前时间
System.out.println(LocalTime.now());
//获取当前时间的 小时
System.out.println(LocalTime.now().getHour());
//当前时间到17:00:00还有多少分钟
System.out.println(LocalTime.now()
.until(LocalTime.of(17,0,0),ChronoUnit.MINUTES));
//当前时间的分钟部分替换成10
System.out.println(LocalTime.now().withMinute(10));
}
Year、YearMonth、MonthDay
分别存储年、年月、月日。
@Test
public void test(){
//当前年
System.out.println(Year.now());
//当前年月
System.out.println(YearMonth.now());
//当前月日
System.out.println(MonthDay.now().format(DateTimeFormatter.ofPattern("MM-dd")));
}
OffsetDateTime、OffsetTime
带有偏移量的日期时间和时间对象,用法和LocalDateTime、LocalTime类似。
@Test
public void test(){
System.out.println(OffsetDateTime.now());
System.out.println(OffsetTime.now());
}
Period
以年,月和日为单位建立数量或时间量,和Duration类似都表示一段时间。
一般用于大单位时间的一段时间。
@Test
public void test(){
//12年5个月60天
System.out.println(Period.of(12,5,60));
}
ZoneId、ZoneOffset、ZonedDateTime
ZoneId代表时区
ZoneOffset代表与UTC时区的偏移量,例如+8:00,范围是-18:00~+18:00。
ZonedDateTime是具有时区的日期时间。 此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。用法和LocalDateTime类似。
@Test
public void test(){
System.out.println(ZonedDateTime.now());
/*
* 偏移量格式
* <ul>
* <li>{@code Z} - for UTC
* <li>{@code +h}
* <li>{@code +hh}
* <li>{@code +hh:mm}
* <li>{@code -hh:mm}
* <li>{@code +hhmm}
* <li>{@code -hhmm}
* <li>{@code +hh:mm:ss}
* <li>{@code -hh:mm:ss}
* <li>{@code +hhmmss}
* <li>{@code -hhmmss}
* </ul>
*/
System.out.println(ZoneOffset.of("+08:00"));
//列出所有时区ID
for (String zoneId : ZoneId.getAvailableZoneIds()) {
System.out.println(zoneId);
}
}
格式化
相关包在java.time.format。
DateTimeFormatter、DateTimeFormatterBuilder
DateTimeFormatter用于打印和解析日期时间对象。
可以使用以下样式格式化:
使用预定义的常量,如ISO_LOCAL_DATE
使用模式字母,如
uuuu-MMM-dd
使用本地化样式,如
long
或medium
DateTimeFormatterBuilder用于更灵活的格式化。可以通过append方法添加很多元素。
@Test
public void test(){
LocalDateTime dateTime=LocalDateTime.now();
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(dateTime.format(formatter));
//解析指定格式的字符串
TemporalAccessor parse = formatter.parse("2022-12-22 15:56:34.555");
DateTimeFormatterBuilder builder=new DateTimeFormatterBuilder();
//获取本地的格式化格式
String s = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.MEDIUM,FormatStyle.MEDIUM, IsoChronology.INSTANCE,Locale.CHINA);
System.out.println(s);
System.out.println(builder.appendPattern(s).toFormatter().format(dateTime));
}