实现了JSR-310规范的新的日期时间的API位于java.time包及子包下。

无特殊说明这些类都是不可变的和线程安全的。

常用的日期时间类

Clock

Java Date时间为什么一直都是CST_java

抽象类,使用时区提供对当前即时,日期和时间的访问的时钟。

该类的实例用于查找当前时刻,可以使用存储的时区来解释当前时刻(当前时间戳转成时区时间的表示)。

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

Java Date时间为什么一直都是CST_Test_02

代表一段时间。

该类以秒和纳秒为单位建立数量或时间量。 它可以使用其他基于持续时间的单位进行访问,例如毫秒、秒、分钟、小时和天。天被视为完全等于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

Java Date时间为什么一直都是CST_java_03

时刻,是时间线上的瞬间点。

该类在时间线上建立单个瞬时点。 这可能用于在程序中记录事件时间戳。

实际上,这一瞬间存在一些限制。 可测量的时间线受限于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

Java Date时间为什么一直都是CST_System_04

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

Java Date时间为什么一直都是CST_Test_05

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

Java Date时间为什么一直都是CST_日期时间_06

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

Java Date时间为什么一直都是CST_Test_07

分别存储年、年月、月日。

@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

Java Date时间为什么一直都是CST_System_08

带有偏移量的日期时间和时间对象,用法和LocalDateTime、LocalTime类似。

@Test
public void test(){
	System.out.println(OffsetDateTime.now());
    System.out.println(OffsetTime.now());
}

 Period

Java Date时间为什么一直都是CST_日期时间_09

以年,月和日为单位建立数量或时间量,和Duration类似都表示一段时间。

一般用于大单位时间的一段时间。

@Test
public void test(){
	//12年5个月60天
    System.out.println(Period.of(12,5,60));
}

 ZoneId、ZoneOffset、ZonedDateTime

Java Date时间为什么一直都是CST_System_10

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

使用本地化样式,如longmedium


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));
}