64从零开始学Java之关于日期时间的新特性

作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦

千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者

前言

在上一篇文章中,壹哥给大家讲解了Java里的格式化问题,这样我们就可以个性化设置日期时间的展示方式了。似乎我们现在已经掌握了不少关于日期和时间的操作技巧,但其实随着时间的不断推移,现实的需求也在不断更新,原先的一些API已经难以满足开发需求了。所以从JDK 8之后,为了满足更多的开发需求,Java给我们增加了不少关于日期时间的新特性,接下来壹哥就带各位来看看这些新特性有哪些。

------------------------------------------------前戏已做完,精彩即开始----------------------------------------------

全文大约【5400】字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

配套开源项目资料

Github:

GitHub - SunLtd/LearnJava

Gitee:

一一哥/从零开始学Java

一. 新特性概述

在JDK 8之前,其实有不少的API都存在着一些问题,日期时间等相关类同样如此。所以从JDK 8开始,Java做了较大的改动,出现了很多新特性。其中,java.time包中了就提供了不少新的日期和时间API,主要如下:

  • 本地日期和时间类:LocalDateTime,LocalDate,LocalTime;
  • 带时区的日期和时间类:ZonedDateTime
  • 时刻类:Instant
  • 时区:ZoneId,ZoneOffset;
  • 时间间隔:Duration。

在格式化操作方面,也推出了一个新的格式化类DateTimeFormatter。

和之前那些旧的API相比,新的时间API严格区分了时刻、本地日期、本地时间和带时区的日期时间,日期和时间的运算更加方便。这些新的API类型几乎全都是final不变类型,我们不必担心其会被修改。并且新的API还修正了旧API中一些不合理的常量设计:

  • Month的范围采用1~12,分别表示1月到12月;
  • Week的范围采用1~7,分别表示周一到周日。

二. LocalDateTime

1. 简介

LocalDateTime是JDK 8之后出现的,用来表示本地日期和时间的类。我们可以通过now()方法,默认获取到本地时区的日期和时间。与之前的旧API不同,LocalDateTime、LocalDate和LocalTime默认会严格按照ISO 8601规定的日期和时间格式进行打印。

2. 获取当前日期和时间

我们可以通过now()方法来获取到当前的日期和时间。我们在执行一行代码时,多少也会消耗一点时间,日期和时间的值可能会对不上,尤其是时间的毫秒数可能会有差异。所以为了保证获取到的日期和时间值差异减少,我们的代码尽量要编写如下:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @author 一一哥Sun 
 */
public class Demo10 {

	public static void main(String[] args) {
		//获取当前日期和时间
		LocalDateTime dt = LocalDateTime.now();
		System.out.println("dt="+dt);
		
		// 转换到当前日期
		LocalDate d = dt.toLocalDate(); 
		System.out.println("date="+d);
		
		// 转换到当前时间
		LocalTime t = dt.toLocalTime(); 
		System.out.println("time="+t);
	}

}

3. of()方法的作用

我们可以通过of()方法,根据指定的日期和时间来创建一个LocalDateTime对象,用法如下:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @author 一一哥Sun 
 */
public class Demo11 {

	public static void main(String[] args) {
		// 根据指定的日期和时间创建LocalDateTime对象

		// 2023-01-25, 月份与之前不同:1-12分别表示1-12个月
		LocalDate date = LocalDate.of(2023, 1, 25);
		// 20:35:48
		LocalTime time = LocalTime.of(20, 35, 48);
		LocalDateTime dt1 = LocalDateTime.of(date, time);
		System.out.println("dt1=" + dt1);

		LocalDateTime dt2 = LocalDateTime.of(2023, 1, 23, 20, 35, 48);
		System.out.println("dt2=" + dt2);
	}
}

4. parse()方法的作用

我们可以使用parse()方法,将一个时间格式的字符串解析为LocalDateTime,用法如下:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @author 一一哥Sun 
 */
public class Demo11 {

	public static void main(String[] args) {
		// 解析时间字符串。T是日期和时间的分隔符
		LocalDateTime dt = LocalDateTime.parse("2023-02-22T20:18:15");
		System.out.println("dt="+dt);
		
		LocalDate date = LocalDate.parse("2012-10-15");
		System.out.println("date="+date);
		
		LocalTime time = LocalTime.parse("16:15:20");
		System.out.println("time="+time);
	}
}

我们要注意,根据ISO 8601规定,日期和时间的分隔符是T,标准格式如下:

  • 日期:yyyy-MM-dd
  • 时间:HH:mm:ss
  • 带毫秒的时间:HH:mm:ss.SSS
  • 日期和时间:yyyy-MM-dd'T'HH:mm:ss
  • 带毫秒的日期和时间:yyyy-MM-dd'T'HH:mm:ss.SSS

5. 时间加减方法

在LocalDateTime中,给我们提供了一系列的加减操作方法,使得我们可以很轻易的实现时间的加减操作,比如给某个日期或时间进行加或减的操作。plusXxx()增加方法如下图所示:

minusXxx()减少方法如下图所示:

import java.time.LocalDateTime;

/**
 * @author 一一哥Sun 
 */
public class Demo13 {

	public static void main(String[] args) {
		// 对日期进行加减操作
		LocalDateTime dt1 = LocalDateTime.now();
		System.out.println("dt1=" + dt1);
		
        // 加3天减6小时:
        LocalDateTime dt2 = dt1.plusDays(3).minusHours(6);
        // 2019-10-31T17:30:59
        System.out.println("dt2=" +dt2); 
        
        // 减1月:
        LocalDateTime dt3 = dt2.minusMonths(1);
        // 2019-09-30T17:30:59
        System.out.println("dt3=" +dt3); 
        
        //加两周
        LocalDateTime dt4 = dt3.plusWeeks(2);
        System.out.println("dt4=" +dt4); 
	}

}

6. 时间调整方法

我们除了可以进行日期和时间的增加、减少操作之外,还可以利用withXxx()方法对日期和时间进行调整,这些方法如下图所示:

从上图可以看出,我们可以对年、月、日、时、分、秒等进行调整,具体含义如下:

  • 调整年:withYear()
  • 调整月:withMonth()
  • 调整日:withDayOfMonth()
  • 调整时:withHour()
  • 调整分:withMinute()
  • 调整秒:withSecond()
import java.time.LocalDateTime;

/**
 * @author 一一哥Sun 
 */
public class Demo14 {

	public static void main(String[] args) {
		// 对日期进行加减操作
		LocalDateTime dt1 = LocalDateTime.now();
		System.out.println("dt1=" + dt1);
		
		// 注意:如果某个月中没有29、30、31等日期,会出现java.time.DateTimeException: Invalid date 'FEBRUARY 31'类似的异常。
        //LocalDateTime dt2 = dt1.withDayOfMonth(31);
		
		//日期变为25日
        LocalDateTime dt2 = dt1.withDayOfMonth(25);
        System.out.println("dt2="+dt2); // 2019-10-31T20:30:59
        
        //月份变成5月
        LocalDateTime dt3 = dt2.withMonth(5);
        //2023-05-25T20:06:06.768
        System.out.println("dt3="+dt3); 
		
        //年份变成2024年
        LocalDateTime dt4 = dt3.withYear(2024);
        //2024-05-25T20:06:06.768
        System.out.println("dt4=" +dt4); 
	}

}

我们在利用withXxx()方法调整月份时,会相应地调整日期。并且要注意,如果某个月中没有29、30、31等日期,则会出现java.time.DateTimeException: Invalid date 'FEBRUARY 31'类似的异常,如下图所示:

7. with()方法

LocalDateTime中有一个通用的with()方法,允许我们进行更复杂的运算,比如获取当月或下个月的第一天、最后一天、第一个周一等操作。

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;

/**
 * @author 一一哥Sun 
 * V我领资料:syc_2312119590 
 * 各平台都有壹哥的同名博客哦
 */
public class Demo14 {
	public static void main(String[] args) {
        //获取本月的第一天0:00时刻:
        LocalDateTime firstDay = LocalDate.now().withDayOfMonth(1).atStartOfDay();
        System.out.println("firstDay="+firstDay);

        //获取本月的最后1天:
        LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
        System.out.println("lastDay="+lastDay);

        //获取下个月的第1天:
        LocalDate nextMonthFirstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfNextMonth());
        System.out.println("nextMonthFirstDay="+nextMonthFirstDay);

        //获取本月的第1个周一
        LocalDate firstWeekday = LocalDate.now().with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
        System.out.println("firstWeekday="+firstWeekday);
	}
}

8. isBefore()与isAfter()方法

如果我们判断两个LocalDateTime的先后顺序,可以使用isBefore()、isAfter()方法。

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * @author 一一哥Sun 
 */
public class Demo16 {

	public static void main(String[] args) {
		LocalDateTime now = LocalDateTime.now();
        LocalDateTime target = LocalDateTime.of(2022, 12, 25, 10, 15, 10);
        //判断A日期在B日期之前
        System.out.println("before?="+now.isBefore(target));
        
        //判断A日期在B日期之前
        System.out.println(LocalDate.now().isBefore(LocalDate.of(2023, 12, 19)));
        
        //判断A时间在B时间之后
        System.out.println(LocalTime.now().isAfter(LocalTime.parse("10:15:20")));
	}

}

9. Duration时间间隔和Period间隔天数

我们可以使用Duration来表示两个时刻之间的持续时间,计算两个时间之间的间隔;用Period来表示两个日期之间的间隔天数,以年、月、日的形式表示,用于计算两个日期之间的间隔

Duration和Period的表示方法也符合ISO-8601的格式,它P...T...的形式表示。P...T之间表示日期间隔,T后面表示时间间隔,如果是PT...的格式,则只表示时间间隔。

所以如果是两个LocalDateTime之间的差值,使用Duration表示的形式就是PT12H10M30S,意思是间隔12小时10分钟30秒。而两个LocalDate之间的差值,用Period表示的形式则是P1M21D,表示间隔1个月21天。

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;

/**
 * @author 一一哥Sun 
 */
public class Demo17 {

	public static void main(String[] args) {
		LocalDateTime start = LocalDateTime.of(2023, 05, 24, 13, 15, 20);
        LocalDateTime end = LocalDateTime.of(2025, 11, 8, 19, 25, 30);
        //计算两个时间的间隔
        Duration d = Duration.between(start, end);
        //PT21582H10M10S,间隔21582小时10分10秒
        System.out.println("duration="+d); 

        //计算两个日期的间隔
        Period p = LocalDate.of(2022, 12, 11).until(LocalDate.of(2025, 2, 22));
        //P2Y2M11D,间隔2个月11天
        System.out.println("period="+p); 
        
        //我们也可以使用ofXxx()或parse()方法直接创建Duration
        //10hours
        Duration d1 = Duration.ofHours(10);
        //2day,4hours,5minutes
        Duration d2 = Duration.parse("P2DT4H5M"); 
        System.out.println("d1="+d1); 
        System.out.println("d2="+d2); 
	}

}

三. ZonedDateTime

1. 简介

我们知道,LocalDateTime表示本地日期和时间,如果我们要表示一个带时区的日期和时间,就需要使用ZonedDateTime了。ZonedDateTime相当于是LocalDateTime + ZoneId,其中ZoneId是java.time引入的新的时区类,它与旧的java.util.TimeZone是有区别的。在ZonedDateTime中也提供了plusDays()等加减操作,使用起来也非常地方便。

2. 创建方式

如果我们想要创建一个ZonedDateTime对象,可以有以下几种方法:

  • 通过now()方法返回ZonedDateTime对象;
  • 通过给LocalDateTime附加ZoneId获取。

接下来壹哥就通过一些具体的案例来给大家展示一下ZonedDateTime到底是怎么创建的。

2.1 now()方法

我们先来看看通过now()方法如何创建一个ZonedDateTime对象。

import java.time.ZoneId;
import java.time.ZonedDateTime;

/**
 * @author 一一哥Sun 
 */
public class Demo18 {

	public static void main(String[] args) {
		//获取默认时区的时间对象
		ZonedDateTime zdt1 = ZonedDateTime.now(); 
		System.out.println("zdt1="+zdt1); 
		
		 //获取指定时区的时间对象
        ZonedDateTime zdt2 = ZonedDateTime.now(ZoneId.of("America/New_York"));
        System.out.println("zdt2="+zdt2); 
	}

}

在这个案例中,我们获得的两个ZonedDateTime对象,它们的时区虽然不同,但时间都是同一时刻的,如果毫秒数不同是在执行语句时有一点时间差。

2.2 附加ZoneId

我们再来通过给LocalDateTime附加ZoneId的方式来获取一个ZonedDateTime对象。

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

/**
 * @author 一一哥Sun
 */
public class Demo19 {

	public static void main(String[] args) {
		LocalDateTime ldt = LocalDateTime.of(2023, 1, 25, 10, 15, 11);
		//获取默认时区的时间对象
		ZonedDateTime zdt1 = ldt.atZone(ZoneId.systemDefault());
		System.out.println("zdt1=" + zdt1);

		//获取指定时区的时间对象
		ZonedDateTime zdt2 = ldt.atZone(ZoneId.of("America/New_York"));
		System.out.println("zdt2=" + zdt2);
	}

}

这种方式创建的ZonedDateTime对象,其日期和时间与LocalDateTime相同,但附加的时区不同,因此是两个不同的时刻。

3. 时区转换

有时我们在项目中需要将A时区的时间转换成B时区的时间,这就需要在两个时区之间进行切换。以前如果我们想实现这种功能,就需要我们自己计算,而且非常的麻烦且复杂,现在新的Java API中直接给我们带来了负责时区转换的方法,这就非常方便了。利用withZoneSameInstant()方法,我们就可以将一个关联的时区转换到另一个时区,转换后的日期和时间也会相应调整。

import java.time.ZoneId;
import java.time.ZonedDateTime;

/**
 * @author 一一哥Sun 
 */
public class Demo20 {
	public static void main(String[] args) {
		//将北京时间转为纽约时间
		//获取北京时区的当前时间
		//注意:这里的时区名字不能随便瞎写,否则会产生java.time.zone.ZoneRulesException: Unknown time-zone ID: Asia/Beijing
        ZonedDateTime zdt1 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        System.out.println("zdt1=" + zdt1);
        
        //将当前时区的时间,转换为纽约时间
        ZonedDateTime zdt2 = zdt1.withZoneSameInstant(ZoneId.of("America/New_York"));
		System.out.println("zdt2=" + zdt2);

        //转换为本地时间
		LocalDateTime ldt = zdt2.toLocalDateTime();
		System.out.println("ldt=" + ldt);
	}
}

注意:

时区的名字不能随便瞎写,否则会产生java.time.zone.ZoneRulesException: Unknown time-zone ID: Asia/Beijing,如下图所示:

另外在时区转换时,由于夏令时的存在,不同的日期转换结果有可能是不同的,有可能会出现两次转换后有1小时的夏令时时差。所以如果我们以后涉及到时区转换时,尽量不要自己计算时差,否则难以正确地处理夏令时。

四. DateTimeFormatter

1. 简介

我们在前面学习Date日期时间对象时,知道该对象默认输出的时间格式其实是不符合大多数的使用场景的,所以一般都需要我们对其进行格式化设置,比如通过printf()方法或SimpleDateFormat类来实现。但是当我们使用新的LocalDateTime或ZonedDateTime进行格式化显示时,就需要使用新的DateTimeFormatter类了。

和SimpleDateFormat不同的是,DateTimeFormatter不但是不可变的对象,且还是线程安全的。编程时我们可以先创建出一个DateTimeFormatter实例对象,然后根据需要引用即可。而之前的SimpleDateFormat则是线程不安全的,使用时只能在方法内部创建出一个新的局部变量。

2. 创建方式

我们要想使用DateTimeFormatter,首先得创建出一个DateTimeFormatter对象,一般有如下两种方式:

  • DateTimeFormatter.ofPattern(String pattern):pattern是待传入的格式化字符串;
  • DateTimeFormatter.ofPattern(String pattern,Locale locale):locale是所采用的本地化设置。

3. 基本使用

了解了创建方式之后,我们就可以来看看该如何进行时间格式化了。

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

/**
 * @author 一一哥Sun 
 */
public class Demo21 {

	public static void main(String[] args) {
		//获取默认的本地时间
		ZonedDateTime zdt = ZonedDateTime.now();
		//获取一个DateTimeFormatter对象,如果需要输出固定字符,可以用'xxx'表示,如'中国时间'
        var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss ZZZZ '中国时间'");
        System.out.println(formatter.format(zdt));

        //获取一个DateTimeFormatter对象,中国时区
        var zhFormatter = DateTimeFormatter.ofPattern("yyyy MMM dd EE HH:mm:ss", Locale.CHINA);
        System.out.println(zhFormatter.format(zdt));
        //改变默认的显示格式,用指定的格式显示
        //System.out.println(DateTimeFormatter.ISO_DATE.format(zdt));

        //获取一个DateTimeFormatter对象,美国时区
        var usFormatter = DateTimeFormatter.ofPattern("E, MMMM/dd/yyyy HH:mm:ss", Locale.US);
        //System.out.println(usFormatter.format(zdt));
        //改变默认的显示格式
        System.out.println(DateTimeFormatter.ISO_DATE_TIME.format(zdt));
	}

}

当我们在格式化字符串时,如果需要输出一些固定的字符,可以用'xxx'的形式来表示。另外我们在调用System.out.println()方法对一个ZonedDateTime,或者LocalDateTime实例进行打印时,实际上调用的是它们的toString()方法。默认的toString()方法显示的字符串是按照ISO 8601格式显示的,我们可以通过DateTimeFormatter预定义的几个静态变量来引用。

五. Instant

1. 简介

壹哥在之前给大家讲过,计算机中存储的当前时间,其实就是一个不断递增的整数值,即从1970年1月1日0分0秒开始以来不断递增的一个整数值。如果我们想要获取这个整数值,可以使用System.currentTimeMillis()方法,该方法会返回一个long型的毫秒值,这就是当前时间的时间戳!

而现在我们其实还可以使用Instant.now()来获取当前的时间戳,效果和System.currentTimeMillis()类似。但Instant获取的时间戳更为精确,其内部采用了两种时间精度,分别是秒和纳秒。

另外Instant还提供了plusXxx和minusXxx增减方法,方便我们进行时间的操作。且Instant作为时间戳对象,我们还可以给它附加上一个时区,创建出对应的ZonedDateTime对象。我们也可以给它关联上指定的ZoneId,得到对应的ZonedDateTime,进而获得对应时区的LocalDateTime,所以我们可以在LocalDateTime、ZoneId、Instant、ZonedDateTime之间互相转换。

2. 使用方法

接下来我们看看Instant的用法。

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

/**
 * @author 一一哥Sun 
 */
public class Demo22 {

	public static void main(String[] args) {
		//获取当前时间的时间戳
		long currentTimeMillis = System.currentTimeMillis();
		System.out.println("currentTimeMillis毫秒级时间戳="+currentTimeMillis);

		//获取当前时间的时间戳
		Instant now = Instant.now();
		System.out.println("now时刻="+now);
		// 秒
        System.out.println("秒级时间戳="+now.getEpochSecond()); 
        // 毫秒
        System.out.println("毫秒级时间戳="+now.toEpochMilli());
		
		//用指定的时间戳创建Instant对象
		Instant ins = Instant.ofEpochSecond(1676262418);
		//获取所在时区的ZonedDateTime对象
		ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());
		System.out.println("zdt="+zdt); 
	}

}

六. 新旧时间API的转换

1. 简介

现在我们知道,在Java中,关于日期和时间的API其实有两套,一套旧的,一套新的。这两套API以JDK 8为分割线,此前的属于旧版API,此后的属于新版API。

  • 旧版API:定义在java.util包中,主要包括Date、Calendar和TimeZone几个类;
  • 新版API:JDK 8之后引入,定义在java.time包中,主要包括LocalDateTime、ZonedDateTime、ZoneId、DateTimeFormatter、Instant等。

这时有些小白就会好奇,这两套时间API我们在开发时该怎么选择?其实壹哥认为,如果大家的项目属于是一个新开发的项目,且你们的Java版本在JDK 8以上,那就采用新版的API吧。但是如果你们的项目涉及到遗留代码,是对旧的项目进行维护或改造,很多遗留代码仍然在使用旧的API,你们壹哥建议大家还是不要改变原有的选择,请继续使用旧版API。

但是如果你们的项目环境已经从低版本的JDK切换到了高本版的JDK,且你们公司要求对项目进行升级改造,我们能不能在新旧两种API之间进行转换呢?其实这也是可以的,今天壹哥就给大家讲一下如何在新旧两套API之间互相转换。

2. 旧转新

首先我们来看看旧的API是如何转成新的API的。比如我们想把旧式的DateCalendar转换为新的API对象,可以通过toInstant()方法转换为Instant对象,然后再继续转换为ZonedDateTime,实现代码如下:

import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;

/**
 * @author 一一哥Sun 
 */
public class Demo24 {

	public static void main(String[] args) {
		//将旧版API中的Date,转为新版API中的Instant对象
		Instant instant = new Date().toInstant();
		System.out.println("instant="+instant);
		
		//将旧版API中的Calendar,转为新版API中的Instant,然后再进一步转为新版的ZonedDateTime:
		Calendar calendar = Calendar.getInstance();
		Instant instant2 = calendar.toInstant();
		ZonedDateTime zdt = instant2.atZone(calendar.getTimeZone().toZoneId());
		System.out.println("zdt="+zdt); 
	}

}

3. 新转旧

旧版API可以转换成新版API,同时我们也可以将新班API转成旧版的API,已实现与原有系统的兼容。如果要实现这一目标,我们需要借助long型的时间戳做一个“中转”,具体实现如下:

import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author 一一哥Sun 
 * V我领资料:syc_2312119590 
 * 各平台都有壹哥的同名博客哦
 */
public class Demo25 {

	public static void main(String[] args) {
		//新版API中的ZonedDateTime,先转为long类型
		ZonedDateTime zdt = ZonedDateTime.now();
		//获取秒级时间戳,转为long类型
		long ts = zdt.toEpochSecond() * 1000;
		System.out.println("ts=" + ts);

		//然后将long类型,转为旧版API中的Date
		Date date = new Date(ts);
		System.out.println("date=" + date);
		
		//将long类型转为旧版API中的Calendar对象
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
		calendar.setTimeInMillis(zdt.toEpochSecond() * 1000);
		System.out.println("calendar=" + calendar);
	}

}

------------------------------正片已结束,来根事后烟----------------------------

七. 结语

至此,壹哥就把日期的格式化操作给大家讲解完毕了,今天的内容比较多且很实用。接下来壹哥就把今日重点给大家总结一下:

  • JDK 8中引入了新的日期和时间API,它们是不变类,默认按ISO 8601标准格式化和解析;
  • 使用LocalDateTime可以非常方便地对日期和时间进行加减、调整日期和时间,且总是返回新对象;
  • 使用isBefore()和isAfter()可以判断日期和时间的先后;
  • 使用Duration和Period可以表示两个日期和时间的“区间间隔”;
  • ZonedDateTime是带时区的日期和时间,可用于时区转换;
  • ZonedDateTime和LocalDateTime可以相互转换;
  • 对ZonedDateTime或LocalDateTime进行格式化,需要使用DateTimeFormatter类;
  • DateTimeFormatter可以通过格式化字符串和Locale对日期和时间进行定制输出;
  • Instant表示高精度时间戳,它可以和ZonedDateTime以及long互相转换;
  • 处理日期和时间时,尽量使用新的java.time包;
  • 新旧两种API之间可以进行转换,旧版转新版可以通过toInstant()方法转换为Instant对象,然后再继续转换为ZonedDateTime;新版转旧版需要借助long型的时间戳做一个“中转”。

如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/103740.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络套接字编程

1.基础预备知识 1.1源ip和目的ip 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址 源IP地址表示发起通信的设备的IP地址。它是数据包的出发点,标识了数据包的来源。当一个设备发送数据包到网络上的其他设备时,该数据包的源IP字段会被…

WSL2的安装与配置(创建Anaconda虚拟环境、更新软件包、安装PyTorch、VSCode)

1. WSL2 安装 以管理员身份打开 PowerShell(“开始”菜单 >“PowerShell” >单击右键 >“以管理员身份运行”),然后输入以下命令: dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /a…

Maven学习

Maven介绍 Maven是Apache的一个开源项目,主要服务于基于Java平台的项目构建,依赖管理和项目信息管理。 Maven可以让团队能够更科学的构建项目,我们可以用配置文件的方式,对项目的名称、描述、项目版本号、项目依赖等信息进行描述…

中文编程开发语言编程实际案例:程序控制灯电路以及桌球台球室用这个程序计时计费

中文编程开发语言编程实际案例:程序控制灯电路以及桌球台球室用这个程序计时计费 上图为:程序控制的硬件设备电路图 上图为:程序控制灯的开关软件截图,适用范围比如:台球厅桌球室的计时计费管理,计时的时候…

RedHat8升级GLIBC_2.29,解决ImportError: /lib64/libm.so.6: version `GLIBC_2.29

问题背景 在做大模型微调训练时,执行python脚本时出现如下报错: 查看当前服务器版本,确实没有GLIBC_2.29的 strings /lib64/libm.so.6 | grep GLIBC_ GLIBC_2.2.5 GLIBC_2.4 GLIBC_2.15 GLIBC_2.18 GLIBC_2.23 GLIBC_2.24 GLIBC_2.25 GLIB…

MySQL的优化利器:索引条件下推,千万数据下性能提升273%

MySQL的优化利器:索引条件下推,千万数据下性能提升273%🚀 前言 上个阶段,我们聊过MySQL中字段类型的选择,感叹不同类型在千万数据下的性能差异 时间类型:MySQL字段的时间类型该如何选择?千万…

[Go版]算法通关村第十八关青铜——透析回溯的模版

目录 认识回溯思想回溯的代码框架从 N 叉树说起有的问题暴力搜索也不行回溯 递归 局部枚举 放下前任Go代码【LeetCode-77. 组合】回溯热身-再论二叉树的路径问题题目:二叉树的所有路径Go 代码 题目:路径总和 IIGo 代码 回溯是最重要的算法思想之一&am…

【Jenkins 安装】

一:安装文件夹准备 在/home/admin 界面下新建三个文件夹,用来安装tomcat、maven 1.打开,/home/admin目录 cd /home/admin 2.新建三个文件夹 mkdir tomcat mkdir maven 二:安装tomcat 1.打开tomcat目录进行tomcat的安装 访问:h…

LSKA(大可分离核注意力):重新思考CNN大核注意力设计

文章目录 摘要1、简介2、相关工作3、方法4、实验5、消融研究6、与最先进方法的比较7、ViTs和CNNs的鲁棒性评估基准比较8、结论 摘要 https://arxiv.org/pdf/2309.01439.pdf 大型可分离核注意力(LSKA)模块的视觉注意力网络(VAN)已…

SpringDoc API文档工具集成SpringBoot - Swagger3

1、引言 之前在Spring Boot项目中一直使用的是SpringFox提供的Swagger库,发现已经超过3年没出新版本了!SpringDoc是一款可以结合Spring Boot使用的API文档生成工具,基于OpenAPI 3,是一款更好用的Swagger库!值得一提的是…

高速下载b站视频的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

JAVA 链式编程和建造者模式的使用(lombok的使用)

0.说明 0.1 链式编程 链式编程的原理是返回一个this对象,也就是返回对象本身,从而达到链式效果。这样可以减少一些代码量,是java8新增的内容。 此处主要介绍在新建对象使用链式编程更加方便的创建对象。链式编程的一些常见用法可以看这个&a…

C++笔记之初始化二维矩阵的方法

C笔记之初始化二维矩阵的方法 —— 2023年5月20日 上海 code review! 文章目录 C笔记之初始化二维矩阵的方法一.常见方法1. 使用数组2. 使用向量3. 使用数组的动态分配4. 使用嵌套的 std::vector 并使用resize方法5. 初始化固定大小的 std::array 二.C中使用vector初始化二维矩…

CSS3属性详解(一)文本 盒模型中的 box-ssize 属性 处理兼容性问题:私有前缀 边框 背景属性 渐变 前端开发入门笔记(七)

CSS3是用于为HTML文档添加样式和布局的最新版本的层叠样式表(Cascading Style Sheets)。下面是一些常用的CSS3属性及其详细解释: border-radius:设置元素的边框圆角的半径。可以使用四个值设置四个不同的圆角半径,也可…

基于Java的新闻发布管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

华为云HECS云服务器docker环境下安装nacos

华为云HECS云服务器,安装docker环境,查看如下文章。 华为云HECS安装docker-CSDN博客 一、拉取镜像 docker pull nacos/nacos-server二、宿主机创建挂载目录 执行如下命令: mkdir -p /usr/local/nacos/logs mkdir -p /usr/local/nacos/con…

基于指数分布优化的BP神经网络(分类应用) - 附代码

基于指数分布优化的BP神经网络(分类应用) - 附代码 文章目录 基于指数分布优化的BP神经网络(分类应用) - 附代码1.鸢尾花iris数据介绍2.数据集整理3.指数分布优化BP神经网络3.1 BP神经网络参数设置3.2 指数分布算法应用 4.测试结果…

模型保存和加载

1、sklearn模型的保存和加载API from sklearn.externals import joblib 保存:joblib.dump(rf, ‘test.pkl’)加载:estimator joblib.load(‘test.pkl’) 2、决策树的模型保存加载案例 保存: import joblib from sklearn.model_selectio…

OpenCV #以图搜图:感知哈希算法(Perceptual hash algorithm)的原理与实验

1. 介绍 感知哈希算法(Perceptual Hash Algorithm,简称pHash) 是哈希算法的一种,主要用来做相似图片的搜索工作。 2. 原理 感知哈希算法(pHash)首先将原图像缩小成一个固定大小的像素图像,然后…

【模式识别】贝叶斯决策模型理论总结

贝叶斯决策模型理论 一、引言二、贝叶斯定理三、先验概率和后验概率3.1 先验概率3.2 后验概率 四、最大后验准则五、最小错误率六、最小化风险七、最小最大决策八、贝叶斯决策建模参考 一、引言 在概率计算中,我们常常遇到这样的一类问题,某事件的发生可…