Java8特性-时间API参照手册(实用版)

Java8特性-时间API参照手册(实用版)

  如果想查看如何记录算法的时间和比较算法的性能,直接跳转1.6节和1.7节。如果想知道如何DIY日期安排,直接跳转2.2节。如果想知道如何将日期格式化输出,直接跳转第5节。如果想知道LocalDateTime和Instant和ZonedDateTime之间的相互转化,直接跳转第6节。



0.前言

0.1章节介绍

  本文讲解的思路首先是Instant和Duration。Instant有两个重要的属性即seconds和nanos,其用来表示时间线上的某个特定时刻,当然这个时刻可读性不强,毕竟没有人会很快地意识到60seconds, 0nanos代表的是1970年1月1日0时1分整;Duration也有两个重要的属性seconds和nanos,可以借助Duration来对两个时刻(时刻至少精确到seconds)求间隔,这样的一个很好的应用就是计算程序运行的时间。

  其次,会讲解LocalTime和LocalDate和LocalDateTime,这些时间表示的方式更贴近人的思维;Period可以来求两个LocalDate的间隔,这样可以弥补Duration要求时间对象必须支持seconds的不足。

  然后,会补充一下讲时区的时间ZonedDateTime,毕竟东八区的当地时间和东九区的当地时间是不一样的。

  再然后,会谈到时间的格式化解析,让时间以你想要的方式进行输出。

  最后,会讲及LocalDateTime和Instant和ZonedDateTime之间的相互转化。



0.2预备知识

  下面的图展示了Instant和LocalDateTime在时间线的表示以及Instant、LocalDateTime,LocalDate,LocalTime的重要属性。

在这里插入图片描述


  下面的图要有一个印象,其目的在于知道函数的参数到底是什么,就好比CharSequence的参数,你要明白可以传String一样。

在这里插入图片描述

TemporalAccessor代表对Temporal对象的只读权限,这可以理解为一个功能性接口,定义了读的权限。

Temporal泛指时间类对象,比如ZonedDateTime,LocalDateTime,这个接口定义了对Temporal对象的读和写权限。

TemporalAdjuster代表的是调整器,它是一个函数式接口,提供一个方法Temporal adjustInto(Temporal temporal);,其表示如何根据一个Temporal对象转换为另一个Temporal对象。TemporalAdjuster有一个工具类TemporalAdjusters,该类预定义了一些方法。这个工具类在DIY定制日程安排上会用得到。



在这里插入图片描述

TemporalAmount泛指时间间隔,比如3小时,5天。它的常见的两个实现类就是Period和Duration,前者用于计算日期的间隔,比如3天,5年。后者用于计算更加精确的时间间隔,比如2秒,3纳秒。



在这里插入图片描述

TemporalField代表时间的字段,这个不好表达它的意思。我就用它的常见的枚举类ChronoField我举例说明,

@Test
public void testChronoField(){

    LocalDateTime now = LocalDateTime.now();
    System.out.println(now);

    //拿到当月的有关日的字段
    int result1 = now.get(ChronoField.DAY_OF_MONTH);
    System.out.println(result1);

    //拿到当周有关日的字段
    int result2 = now.get(ChronoField.DAY_OF_WEEK);
    System.out.println(result2);

    int result3 = now.get(ChronoField.DAY_OF_YEAR);
    System.out.println(result3);
}

测试结果:

2020-10-14T14:27:52.652
14
3
288

DAY_OF_MONTH,指的是当天是当月的第几天。

DAY_OF_WEEK,指的是当天是当周的第几天。

DAY_OF_YEAR,指的是当天是当年的第几天。



在这里插入图片描述

TemporalUnit代表的是时间单位,比如小时,分钟,天等等。它的常用的枚举类就是ChronoUnit。



1.Instant和Duration

1.1Instant实例创建

  Instant代表的是时间线的一个时刻,它有两个重要的属性seconds和nanos来表示这个时刻。不过需要注意的是nanos的部分永远是正数,详情见下面代码。

    //代表seconds的部分
    private final long seconds;
    //代表nanos的部分,这个部分的范围是0--999 999 999,其作用是用来修正seconds。

    //比如 纪元即1970年1月1日00:00:00  的前1纳秒的表示不是 0 seonds -1 nanos 而是-1seconds 999 999 999 nanos
    private final int nanos;

Instant类常见的创建对象的对象方式分为两类:

//创建当前时间的Instant对象
static Instant now();

//下面的三个方法都是传入相对于纪元时刻的秒数或是毫秒数来创建Instant对象
static Instant ofEpochMilli(long epochMilli) ;
static Instant ofEpochSecond(long epochSecond) ;
static Instant ofEpochSecond(long epochSecond, long nanoAdjustment) ;


测试代码:

 @Test
    public void testCreateInstant(){
        //创建当前时刻
        Instant now = Instant.now();

        //创建纪元后1s的时刻
        Instant instant1 = Instant.ofEpochMilli(1000);
        Instant instant2 = Instant.ofEpochSecond(1);
        Instant instant3 = Instant.ofEpochSecond(1, 0);


        System.out.println(now);
        System.out.println(instant1);
        System.out.println(instant2);
        System.out.println(instant3);

    }

测试结果

2020-10-13T09:00:38.937Z
1970-01-01T00:00:01Z
1970-01-01T00:00:01Z
1970-01-01T00:00:01Z



1.2Instant比较

  Instant的常见一个问题就是比较。由于Instant,LocalTime,LocalDate等时间类都实现了Comparable接口,所以可以用compareTo方法进行比较,其次Instant类内置了isBefore和isAfter方法也可以用来比较,最后也可以通过Duration来进行比较。

API如下:

//Instant类的方法
int compareTo(Instant another);
    
//Instant类的方法
boolean isBefore(Instant otherInstant);
boolean isAfter(Instant otherInstant);

//Duration类的方法
//判断时间间隔是否为负
boolean isNegative() ;

测试代码:

  /**
     * 1.比较两个Instant的实例对象
     * 1.1.Instant和LocalDate,LocalTime,LocalDateTime.
     *   以及用于比较Instant,LocalTime,LocalDateTime的Duration
     *          比较LocalDate的Period都实现了
     *          Comparable接口。
     *
     *     所以可以使用int compareTo(Instant another)方法进行两个Instant实例对象的比较
     *
     * 1.2.通过 boolean isAfter(Instant another) 或是 boolean isBefore(Instant another)比较
     *
     * 1.3 通过Duration 的静态方法
     *               public static Duration between(Temporal startInclusive, Temporal endExclusive)
     *     获得两个时间点Instant的间隔Duration后。
     *     调用Duration对象的boolean isNegative()方法来判断,如果为true,则前者更晚,如果为false,则后者更晚
     */
    @Test
    public void  compareInstant(){
        Instant min = Instant.MIN;
        Instant max = Instant.MAX;

        //1.通过int compareTo(T another)比较
        if (max.compareTo(min)>0){
            System.out.println("max的时间更晚");
        }

        //2.通过 boolean isAfter(Instant another) 或是 boolean isBefore(Instant another)比较
        if (max.isAfter(min)){
            System.out.println("max的时间更晚");
        }

        //3. 通过boolean isNegative()方法比较
        Duration duration = Duration.between(min, max);
        if (!duration.isNegative()){
            System.out.println("max的时间更晚");
        }

    }

测试结果:

max的时间更晚
max的时间更晚
max的时间更晚



1.3Instant的类似get和set

  见下面的API解释

//将Instant转换为1970-01-01T00:00:00Z的时期的毫秒数
long toEpochMilli() ;
//获得nanos部分
int getNano()  ;
//获得seconds部分
long getEpochSecond()  ;

//获得特定field部分,这个field要求必须是ChronoField的下面4个枚举对象
//NANO_OF_SECOND
//MICRO_OF_SECOND
//MILLI_OF_SECOND
//INSTANT_SECONDS:
int get(TemporalField field);
long get(TemporalField field);

//将特定字段转为新值,并返回一个新的Instant 对象
//field的要求如get方法
Instant with(TemporalField field, long newValue)  

测试代码:

 @Test
    public void testInstantGetAndWith(){
        /**
         * 类似于Get
         */
        Instant now = Instant.now();
        long epochSecond = now.getEpochSecond();
        int nano = now.getNano();
        //这里与Instant的创建实例方法:static Instant ofEpochMilli(long epochMilli)对应
        //将now转为毫秒数
        long epochMilli = now.toEpochMilli();
        //获得Instant的nano部分,并转为Micro
        long aLong = now.getLong(ChronoField.MICRO_OF_SECOND);
        System.out.println(now);
        System.out.println(epochSecond);
        System.out.println(nano);
        System.out.println(epochMilli);
        System.out.println(aLong);

        /**
         * 类似于set
         * 但实际上Instant是一个不可变的类,这个方法会返回一个新的实例。
         */
        Instant instant1 = now.with(ChronoField.INSTANT_SECONDS, 0);
        Instant instant2 = now.with(ChronoField.NANO_OF_SECOND, 0);
        System.out.println(instant1);
        System.out.println(instant2);
    }

测试结果:

2020-10-14T01:16:36.853Z
1602638196
853000000
1602638196853
853000
1970-01-01T00:00:00.853Z
2020-10-14T01:16:36Z



1.4Instant的plus和minus

  这个太简单,比如在Instant实例对象的基础上添加1个ns等等。

@Test
public void testInstantPlus(){
    Instant instant1 = Instant.now();
    Instant instant2 = instant1.plusMillis(3);
    Instant instant3 = instant1.minusNanos(3);
}

类似的,敲一敲就行了。



1.5Duration的实例创建

  Duration的两个常见的实例域seconds和nanos,这里和Instant是类似的,seconds表示秒的部分,nanos部分用于修正,范围为0到999 999 999.

创建Duration的实例常见的方法是between方法和of方法,如下面所示:

//Temproal代表的实例对象必须要有seconds部分,也就是说LocalDate不能当做参数传入
//这个方法的含义就是取两个Temporal对象的差值
static Duration between(Temporal startInclusive, Temporal endExclusive)  ;

//获取大小为amount,单位为unit的Duration   
static Duration of(long amount, TemporalUnit unit) 
//获取大小为days,单位为Day的Duration    
static Duration ofDays(long days) 
  
static Duration ofHours(long hours) 

static Duration ofMillis(long millis)  
//............. 还有一些ofXXX的方法就不展示了

测试代码:

@Test
public void testCreateDuration2(){
    Instant now = Instant.now();
    //加三个小时
    Instant over3Hours = now.plus(3, ChronoUnit.HOURS);

    //between方法,创建间隔为3小时的Duration
    Duration duration1 = Duration.between(now, over3Hours);

    //of创建间隔为3小时的Duration
    Duration duration2 = Duration.ofHours(3);
    Duration duration3 = Duration.of(3, ChronoUnit.HOURS);

    if (duration1.equals(duration2) && duration1.equals(duration3)){
        System.out.println("三者相等");
    }
}

测试结果:

三者相等



1.6Duration来计算算法时间

  这一小节用Duration来计算算法的时间,相关的解释已经放在了代码内部。

/**
 * 2.计算算法的执行时间
 *        Duration可以计算两个时刻的差值,所以常用Duration来计算算法的执行时间
 *        Duration  有两个域存储时间差  seconds  和 nanos
 *                     long seconds; 表示秒的部分
 *                     int  nanos;   表示纳秒的部分(范围0到 999 999 999),用于修正seconds
 *
 *        int  getNano() :获得nano的部分
 *      .
 *        long getSeconds() :获得seconds的部分
 *
 *    2.1如果精确度不高,那么可以直接调用getSeconds() 获得seconds的部分
 *
 *    2.2
 *    long toDays()
 *    long toHours()
 *    long toMinutes()
 *    上面三个方法是将seconds 的部分进行转化,忽略nanos部分。
 *    底层就是除法,所以会产生整数截断情况。
 *
 *    下面两个办法是将seconds和nanos进行转化。
 *    long toMillis()
 *    long toNanos()
 *
 *    一般情况下,转换不会出现溢出情况。
 *      毕竟当Duration跨度300年左右时间,toNanos才会产生溢出
 *
 *     假如我就是想得到us呢?
 *     你得到ns后除以1000就可以了呀
 */
@Test
public void calculateAlgorithm(){

    Instant begin  = Instant.now();
    /**    模拟算法执行  **/
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    /**    模拟算法执行  **/
    Instant end   = Instant.now();

    Duration duration = Duration.between(begin, end);

    //1. long  getSeconds()
    long seconds = duration.getSeconds();
    System.out.println("算法用时"+seconds+"s");

    //2. long   toHours()
    long hours = duration.toHours();
    System.out.println("算法用时"+hours+"h");

    //3. long  toMillis()
    //   long  toNanos()
    long millis = duration.toMillis();
    System.out.println("算法用时"+millis+"ms");
    long nanos = duration.toNanos();
    System.out.println("算法用时"+nanos+"ns");


}

测试结果

算法用时1s
算法用时0h
算法用时1001ms
算法用时1001000000ns



1.7Duration来比较两个算法快慢

  这一小节讲解如何通过Duration来比较两个算法的快慢.

/**
 * 3.比较算法的快慢
 *     1.通过获取算法的准确时间然后比较(见2)
 *
 *      以比较一个算法是不是另一个算法的10倍为例
 */
@Test
public void compareAlgorithm(){
    Instant begin1  = Instant.now();
    /**    模拟算法1执行  **/
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    /**    模拟算法1执行  **/
    Instant end1   = Instant.now();


    Instant begin2  = Instant.now();
    /**    模拟算法2执行  **/
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    /**    模拟算法2执行  **/
    Instant end2   = Instant.now();


    Duration duration1 = Duration.between(begin1, end1);
    Duration duration2 = Duration.between(begin2, end2);

    if(duration1.multipliedBy(10).minus(duration2).isNegative()){
        System.out.println("算法1至少是算法2的10倍速");
    }
    if (duration1.toNanos()*10<duration2.toNanos()){
        System.out.println("算法1至少是算法2的10倍速");
    }

}

测试结果:

算法1至少是算法2的10倍速
算法1至少是算法2的10倍速



1.8关于Duration的补充

  Duration代表的是一个时间间隔,这个时间间隔也可能是代表是负数,想象一下,假如有人往between方法传入的参数刚好弄反了呢?为了避免这个情况,可以采用一个方法abs(),它的含义就是取Duration的绝对值。

测试代码:

@Test
    public void  testABS(){
        Instant min = Instant.MIN;
        Instant max = Instant.MAX;

        //我把小的时刻传到后面的参数
        Duration duration = Duration.between(max, min);

        Duration duration1 = duration.abs();
        Duration duration2 = duration1.abs();
        System.out.println(duration);
        System.out.println(duration1);
        System.out.println(duration2);
    }

测试结果:

PT-17531640008784H0.000000001S
PT17531640008783H59M59.999999999S
PT17531640008783H59M59.999999999S



2.LocalDateTime

  LocalDateTime代表的本地的时间,比如2020年9月12日12点20分37秒,与此相对的是时区时间ZonedDateTime,比如北京2020年9月12日12点20分37秒的时刻就对应东京2020年9月12日13点20分37秒,时区时间后面会讲到,这里就不赘述。与LocalDateTime类似的就是LocalDate和LocalTime,LocalDateTime就是由LocalDate和LocalTime构成的,懂了LocalDateTime,其他两个也就可以猜个七七八八,所以这两个也不再赘述。

2.1LocalDateTime实例创建

  主要还是两种方法,一个是now,获取当前时间,另外一个是of,获取定制时间

//获得系统的当地时间
static LocalDateTime now()  ;
//从指定时区的系统时钟获取当前的日期时间
static LocalDateTime now(ZoneID id);

//获得定制的本地时间
static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute)   
static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second)  
//..............还有很多of的重载方法,参照API即可

测试代码:

  @Test
    public void testCreateLocalDateTime(){
        //获得系统默认的本地时间
        LocalDateTime now0= LocalDateTime.now();
        //获得特定时区的当地时间
        LocalDateTime now1 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        System.out.println(now0);
        System.out.println(now1);


        LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.now());
        System.out.println(localDateTime);
    }

测试结果:

2020-10-13T19:45:20.168
2020-10-13T19:45:20.169
2020-10-13T19:45:20.169


  这里有一个问题就是为什么能获得系统的默认当地时间而不是GMT(格林威治时间)呢。这是因为每个时区都有一个特定的ID,当你执行创建LocalDateTime对象的时候,如果没有显式指定ZoneID,那么系统会获取你本地的默认ID,然后创建LocalDateTime对象。

参考代码:

打印所有时区ID:

/**
 * 时区是动态获取的,并不是枚举量或是常量。
 * 时区都对应一个ID,比如Asia/Aden
 * 
 * 打印时区ID的数量,并打印所有id
 */
@Test
public void testGetAvailableZoneId(){
    Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
    System.out.println(availableZoneIds.size());
    availableZoneIds.forEach(System.out::println);
}

600
Asia/Aden
America/Cuiaba
Etc/GMT+9
Etc/GMT+8

Europe/Athens
US/Pacific
Europe/Monaco


获得当地时区ID:

@Test
public void testLocalZonedId(){
    ZoneId zoneId = ZoneId.systemDefault();
    System.out.println(zoneId.getId());
}

测试结果:

Asia/Shanghai



2.2其他重要的方法实践(定制日程)

  LocalDateTime和Instant其实差不多,只不过一个是机器看着方便,一个是人看着方便,比如plus和get方法都差不多。这里主要谈谈日程安排的一些应用就可以了。这里常用的就是with方法了。

//传入一个时间矫正器,并返回一个新的LocalDateTime
public LocalDateTime with(TemporalAdjuster adjuster)

测试代码如下:

  @Test
    public void  testWith(){
        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        //本月的头天
        LocalDateTime localDateTime = now.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println(localDateTime);

        //下周周五
        LocalDateTime localDateTime1 = now.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
        System.out.println(localDateTime1);

        //传入一个TemporalAdjustor函数式接口对象,定义下一个工作日
       LocalDateTime nextWorkDay= now.with(ele->{
            LocalDateTime temp = (LocalDateTime)ele;
            int weekValue = temp.getDayOfWeek().getValue();
            //如果是周五周六周日,那么下个工作日就是下一个周一
            if (weekValue/5 ==1){
                return temp.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
            }
            //如果是周一到周四,则返回当日的明天
            return temp.plusDays(1);
        });

        System.out.println(nextWorkDay);
    }

测试结果:

2020-10-14T10:26:08.724
2020-10-01T10:26:08.724
2020-10-16T10:26:08.724
2020-10-15T10:26:08.724



3.Period

  与Duration相对的就是Period,这个Period对象用于表示两个LocalDate的间隔。

测试代码:

@Test
public void testPeriod(){
    //中国建国日
    LocalDate  foundedDay = LocalDate.of(1949,10,1);
    LocalDate now = LocalDate.now();

    Period period = Period.between(foundedDay, now);
    System.out.println(period);
}

测试结果:

P71Y13D



4.ZonedDateTime

  这是一个与时区相关的日期表示形式,它的很多方法其实和LocalDateTime也差不多,下面就展示时区的切换:

测试代码:

@Test
public void testZonedTimeTransfer(){
    ZonedDateTime now = ZonedDateTime.now();
    System.out.println(now);
    //获得美国纽约此时的时区时间
    ZonedDateTime zonedDateTime = now.withZoneSameInstant(ZoneId.of("America/New_York"));
    System.out.println(zonedDateTime);

    //切换成当地时间相同的美国纽约时间
    ZonedDateTime zonedDateTime1 = now.withZoneSameLocal(ZoneId.of("America/New_York"));
    System.out.println(zonedDateTime1);
}

测试结果:

2020-10-14T10:45:22.357+08:00[Asia/Shanghai]
2020-10-13T22:45:22.357-04:00[America/New_York]
2020-10-14T10:45:22.357-04:00[America/New_York]



5.时间的格式化解析

  如何让时间格式化打印输出呢?这里要涉及到一个类:DateTimeFormatter.这个类已经预定义了一些标准的格式,当然,也提供了方法让我们自己设计输出的格式。下面我摘录了Java核心技术卷2预定义的标准格式和自定义格式需要用到的参数(也可以查看官网):

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述

在这里插入图片描述


关于格式化解析有两类重要的方法,一类是将String转为特定的日期类型,一类是将日期类型转为特定的日期格式并打印输出:

//创建定制格式的DateTimeFormatter
static DateTimeFormatter	ofPattern(String pattern);
//与此相对的就是预定义的DateTimeFormatter,可以参照代码

    
//将特定的时间对象按照DateFormatter的格式打印输出
String	format(TemporalAccessor temporal);

//通过调用特定时间的类型的静态parse方法,传入相应的DateTimeFormatter和String 文本
//以LocalDateTIme的静态方法 parse为例
static LocalDateTime	parse(CharSequence text, DateTimeFormatter formatter);

测试代码:

 @Test
    public void  test(){

        //内置解析器
        DateTimeFormatter isoLocalDateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

        String result2 = isoLocalDateTimeFormatter.format(LocalDateTime.now());
        System.out.println(result2);


        //DIY定制解析器
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
        String result3 = dateTimeFormatter.format(LocalDateTime.now());
        String result4 = dateTimeFormatter.format(ZonedDateTime.now());
        System.out.println(result3);
        System.out.println(result4);


        //静态方法:利用特定的日期格式和特定的格式器,转换为对应的日期。
        LocalDateTime localDateTime = LocalDateTime.parse("2020年10月13日 14:14:05", dateTimeFormatter);
        System.out.println(localDateTime);

    }

测试结果:

2020-10-14T11:06:45.42
2020年10月14日 11:06:45
2020年10月14日 11:06:45
2020-10-13T14:14:05



6.LocalDateTime和Instant和ZonedDateTime的相互转化

  当然,转化的方法不止一种,我就附上我用到的方法。

测试代码:

@Test
public void transfer(){
    //创建三个不同类型对象
    LocalDateTime localDateTime = LocalDateTime.now();
    Instant instant = Instant.now();
    ZonedDateTime zonedDateTime = ZonedDateTime.now();
    System.out.println(localDateTime);
    System.out.println(instant);
    System.out.println(zonedDateTime);
    System.out.println("..............................分割线.......................");
    /**
     * LocalDateTime转为ZonedTime
     */
    //将当地时间转为特定时区的时间
    ZonedDateTime zonedDateTime1 = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
    //将当地时间转为系统默认时区的时间
    ZonedDateTime zonedDateTime2 = localDateTime.atZone(ZoneId.systemDefault());
    //效果同上面两个
    ZonedDateTime zonedDateTime3 = ZonedDateTime.of(localDateTime, ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime4 = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
    System.out.println(zonedDateTime1);
    System.out.println(zonedDateTime2);
    System.out.println(zonedDateTime3);
    System.out.println(zonedDateTime4);
    System.out.println("..............................分割线.......................");
    /**
     * LocalDateTime转为Instant
     */
    //此方法需要指定LocalDateTime所在的时区。ZoneOffset是ZoneID的子类
    Instant instant1 = localDateTime.toInstant(ZoneOffset.of("+8"));
    System.out.println(instant1);
    System.out.println("..............................分割线.......................");

    /**
     * Instant转为LocalDateTime
     */
    LocalDateTime localDateTime1 = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Shanghai"));
    System.out.println(localDateTime1);
    System.out.println("..............................分割线.......................");
    /**
     * Instant转为ZonedDateTime
     */
    ZonedDateTime zonedDateTime5 = instant.atZone(ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zonedDateTime6 = ZonedDateTime.ofInstant(instant, ZoneId.of("Asia/Shanghai"));
    System.out.println(zonedDateTime5);
    System.out.println(zonedDateTime6);
    System.out.println("..............................分割线.......................");


    /**
     * ZonedDateTime转为Instant
     */
    Instant instant2 = zonedDateTime.toInstant();
    System.out.println(instant2);
    System.out.println("..............................分割线.......................");

    /**
     * ZonedDateTime转为LocalDateTime
     */
    LocalDateTime localDateTime2 = zonedDateTime.toLocalDateTime();
    System.out.println(localDateTime2);
}

测试结果:

2020-10-14T12:29:16.628
2020-10-14T04:29:16.628Z
2020-10-14T12:29:16.629+08:00[Asia/Shanghai]
…分割线…
2020-10-14T12:29:16.628+08:00[Asia/Shanghai]
2020-10-14T12:29:16.628+08:00[Asia/Shanghai]
2020-10-14T12:29:16.628+08:00[Asia/Shanghai]
2020-10-14T12:29:16.628+08:00[Asia/Shanghai]
…分割线…
2020-10-14T04:29:16.628Z
…分割线…
2020-10-14T12:29:16.628
…分割线…
2020-10-14T12:29:16.628+08:00[Asia/Shanghai]
2020-10-14T12:29:16.628+08:00[Asia/Shanghai]
…分割线…
2020-10-14T04:29:16.629Z
…分割线…
2020-10-14T12:29:16.629


完结撒花!!!在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值