IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 还在用Java Date,新姿势了解下? -> 正文阅读

[Java知识库]还在用Java Date,新姿势了解下?

从JDK1.8开始,Java提供了java.time包,该包用于描述ISO日历系统中的日期和时间。通过该包下的类可以实现分别访问日期、时间和时间戳等对象。 不像java.util.Date, 一个类包含日期和时间所有信息。比如你可以使用LocalDate对象来表示日期,使用LocalTime对象表示时间,用LoalDateTime对象表示日期时间。

概述

? 从JDK1.8开始,Java增加了java.time包,此包下定义了代表日期时间概念的类,包括瞬间、持续时间、日期、时间、时区和周期。 这些类基于ISO日历系统定义的,他们都是不可变的且线程安全的。java.time包中定义了很多用于描述时间的类,这里我们选择其中一部分进行讲解,首先我们看下他们的类关系图,如下所示:

在这里插入图片描述

  • Temporal:日期、时间和偏移时间的接口类,它定义了Temporal接口对象的加减运算、创建对象等方法。
  • TemporalAccessor:定义了访问Temporal对象的方法,比如获取日期对象中的年、月、日属性。
  • TemporalAdjuster:修改Temporal的接口。
  • LocalDate:用于表示日期,比如“2022-3-30”。
  • LocalTime:用于表示时间,比如“16:15:45.326657”。
  • LocalDateTime:用于表示日期和时间,但不包含时区,时间精确到纳秒,比如“2022-03-30T16:15:45.836657”。
  • ZoneId:用于表示时区ID,有三种表达形式:
    • 以字符’ Z’或者’+’、’-‘开头,其中’Z’表示0时区,’+‘表示东时区,’-'表示西时区,比如"+8"表示东八区;
    • 以’UTC’、‘GMT’、'UT’为前缀,加上偏移时间,比如"UTC+8"表示东八区;
    • 基于地区定义的ID,比如"Asia/Shanghai";
  • Instant:用于表示某个瞬间,可以理解为时间戳;
  • Clock:用于使用时区访问瞬间、日期和时间的时钟对象;Clock是抽象类,有四个嵌套子类:FixedClock、OffsetClock、SystemClock、TickClock。
  • ZonedDateTime:用于表示包含时区信息的日期时间类。LocalDateTime不存储时区信息,如果想要对象保存时区信息,那么可该用ZonedDateTime对象。从上面的类图也可看出该类依赖LocalDateTime、ZoneId和ZoneOffset;
  • ZoneOffset:用于描述与格林威治/UTC 的时区偏移量,比如我国的时区偏移量为 “+08:00”。

接下来我们来了解下其中的几个类,他们分别是LocalDate, LocalTime和LocalDateTime(备注,文中的代码是基于JDK11,有部分方法在JDK1.8上未定义)。

LocalDate

? LocalDate 是用于描述ISO-8601日历系统中日期,但不包括时区时间信息。LocalDate 正如其名,此类不存储时间或时区,也就是说不能通过LocalDate对象获取时间或者时区;它只用于描述日期,通常为“年-月-日”。通过LocalDate提供的实例方法也可以访问其他日期字段,比如一年中的某一天、一周中的某一天和一年中某一周。LocalDate对象是不可以变对象,正因如此它也是线程安全的。

常见方法

now()

? now()有三个重载方法,他们最终是通过ofInstant方法实现创建LocalDate对象,具体细节在此不展开,感兴趣的同学可以看下源码,我们主要看下这三个重载方法的使用。

private void localDate() {
    //不指定时区,则使用系统默认时区
    LocalDate localDate = LocalDate.now();
    Log.print("localDate: " + localDate);
  
    //通过Clock对象创建LocalDate,Clock对象指定的时区为西10区,
    LocalDate localDateByClock = LocalDate.now(Clock.system(ZoneId.of("UTC-10")));
    Log.print("localeDate by clock: " + localDateByClock);
  
    //通过ZoneId对象创建LocalDate,时区为西10区;
    LocalDate localDateByZoneId = LocalDate.now(ZoneId.of("UT-9"));
    Log.print("localeDate by zone id: " + localDateByZoneId);
}

输出结果如下:

localDate: 2022-03-27
localeDate by clock: 2022-03-26
localeDate by zone id: 2022-03-27

代码运行的时间是2022年3月27日17:30,所在的时区为“UTC+8”,所以第一行打印是"2022-03-27",localDateByClock对象指定的时区为“UTC-10”,所以与localDate所在的时区相差18个小时,所以第二行打印为"2022-03-26",localDateByZoneId 指定的时区与localDate所在的时区相差17个小时,所以第三行打印为"2022-03-27"。(备注,文中的Log.print()是对系统打印的简单封装)

ofxxx()

LocalDate有多个ofxxx()方法,我们通过例子来看下其中的几个:

private void localeDateOf() {
    //of(int year, int month, int dayOfMonth)通过指定整数年月日创建LocalDate对象
    LocalDate localDate = LocalDate.of(2022, 2, 28);
    Log.print("localDate: " + localDate);
  
    //of(int year, Month month, int dayOfMonth)通过整数年日和Month对象创建LocalDate对象。
    LocalDate localDateOf = LocalDate.of(2022, Month.FEBRUARY, 28);
    Log.print("localDateOf: " + localDateOf);
  
    //ofYearDay(int year, int dayOfYear)通过年和一年中的第几天创建LocalDate对象
    LocalDate localDateYearOfDay = LocalDate.ofYearDay(2022, 60);
    //2020年为闰年,所以对应的日期为2020-02-29
    LocalDate localDate2020OfDay = LocalDate.ofYearDay(2020, 60);
    Log.print("localDateYearOfDay: " + localDateYearOfDay + ", localDate2020OfDay: " + localDate2020OfDay);
  
    //通过Instant和ZoneId(UTC-10)对象创建LocalDate对象,当前时间是17:30,
    //所以创建的LocalDate对应的日期是2022-03-26
    LocalDate localDateByInstant = LocalDate.ofInstant(Instant.now(), ZoneId.of("UTC-10"));
    //采用系统默认ZoneID(UTC+8)创建LocalDate对象
    LocalDate localDateByInstantDefaultZoneDate = LocalDate.ofInstant(Instant.now(),
                                                                      ZoneId.systemDefault());
    Log.print("localDateByInstant: " + localDateByInstant 
              + ", localDateByInstantDefaultZoneDate: " + localDateByInstantDefaultZoneDate);
}
localDate: 2022-02-28
localDateOf: 2022-02-28
localDateYearOfDay: 2022-03-01, localDate2020OfDay: 2020-02-29
localDateByInstant: 2022-03-26, localDateByInstantDefaultZoneDate: 2022-03-27

运算

? 运算包括对年、月、周、日的加减操作,对LocalDate对象的加减操作返回的是LocalDate对象的副本,LocalDate对象本身不会发生变化,因为LocalDate对象是不可变的。具体看实际例子

/**
 * LocalDate 年、月、周、日的加减运算
 */
private void localDateOperation() {
    LocalDate localDate = LocalDate.now();
    Log.print("localDate: " + localDate + ", plus day: " + localDate.plusDays(1) 
    + ", plus week: " + localDate.plusWeeks(1)
    + ", plus month: " + localDate.plusMonths(1)
    + ", plus year: " + localDate.plusYears(1));

    Log.print("localDate: " + localDate + ", minus day: " + localDate.minusDays(1) 
    + ", minus week: " + localDate.minusWeeks(1)
    + ", minus month" + localDate.minusMonths(1)
    + ", minus year: " + localDate.minusYears(1));

}
localDate: 2022-03-27, plus day: 2022-03-28, plus week: 2022-04-03, plus month: 2022-04-27, plus year: 2023-03-27
localDate: 2022-03-27, minus day: 2022-03-26, minus week: 2022-03-20, minus month2022-02-27, minus year: 2021-03-27

从上述的打印也能看出,对localDate 中的属性加减运算,并没有改变localDate

格式化

? 可将LocalDate对象格格式化,也可通过LocalDate.parse()方法将格式化后的字符生成LocalDate对象。关于格式化字符模式可参考DateTimeFormatterBuilder#appendPattern(String pattern)方法注释

private void localDateFormat() {
    LocalDate localDate = LocalDate.now();
    //将LocalDate格式化。
    String formated = localDate.format(DateTimeFormatter.ofPattern("YYYY-MM-dd"));
    Log.print("formated date: " + formated);
  
    //通过parse方法将格式化的日期转换成LocalDate对象,也可通过parse的重载方法指定格式化模式生成LocalDate对象
    LocalDate parsedDate = LocalDate.parse(formated);
    Log.print("parsed date: " + parsedDate);
}
formated date: 2022-03-27
parsed date: 2022-03-27

其他

LocalDate还提供了其他一些类和实例的方法,这里我们通过下面的例子了解下:

private void localDateOther() {
    LocalDate localDate = LocalDate.now();
    //年份
    int year = localDate.getYear();
    //月份
    int month = localDate.getMonthValue();
    //几号
    int day = localDate.getDayOfMonth();
    //当前日期是这一年的第几天
    int dayOfYear = localDate.getDayOfYear();
    //星期
    DayOfWeek dayOfWeek =  localDate.getDayOfWeek();
    Log.print("localeDate: " + localDate + ", year: " + year
    + ", month: " + month + ", day of month: " + day
    + ", dayOfYear: " + dayOfYear + ", dayOfWeek: " + dayOfWeek
    );
  
    //当前localDate对应的年份有几天
    int lenOfYear = localDate.lengthOfYear();
    //当前localDate对应的月份有几天
    int lenOfMonth = localDate.lengthOfMonth();
    //是否是闰年
    boolean leap = localDate.isLeapYear();
    Log.print("length of year: " + lenOfYear + ", length of month: " + lenOfMonth
    + ", is leap year: " + leap);
  
    //localDate对象基础上替换日数,如果日数不合法则抛出异常
    LocalDate dayLocalDate = localDate.withDayOfMonth(12);
    //localDate对象基础上替换月份,如果月份不合法则抛出异常
    LocalDate monthLocalDate = localDate.withMonth(2);
    //localDate对象基础上替换年份,如果年份不合法则抛出异常
    LocalDate yearLocalDate = localDate.withYear(2020);
    Log.print("dayLocalDate: " + dayLocalDate
     + ", monthLocalDate: " + monthLocalDate
     + ", yearLocalDate: " + yearLocalDate
     );
  
     //从TemporalAccessor接口对象中解析出日期,如果该对象中没有日期信息则会抛出异常
     LocalDate from = LocalDate.from(LocalDate.of(2022, 3, 27));
     Log.print("from: " + from);

}

输出结果如下:

localeDate: 2022-03-27, year: 2022, month: 3, day of month: 27, dayOfYear: 86, dayOfWeek: SUNDAY
length of year: 365, length of month: 31, is leap year: false
dayLocalDate: 2022-03-12, monthLocalDate: 2022-02-27, yearLocalDate: 2020-03-27
from: 2022-03-27

LocalTime

? LocalTime 是用于描述ISO-8601日历系统中不含时区的时间,比如:18:15:30。和LocalDate一样,LocalTime也是不可变对象,LocalTime精确到纳秒,比如"13:45.30.123456789"。同样,LocalTime也不存储时区信息,也就是说不能通过LocalTime对象获时区信息。

常见方法

now()

now()有三个重载方法,最终是通过ofInstant方法创建LocalTime对象。

private void localTime() {
    //以系统默认时区创建LocalTime对象
    LocalTime localTime = LocalTime.now();
    Log.print("localTime: " + localTime);
  
    //通过Clock对象创建LocalTime对象,因为代码运行所在的时区为UTC+8, 所以localTimeByClock代
    //表的时间比localTime对应的时间要早一个小时
    LocalTime localTimeByClock = LocalTime.now(Clock.system(ZoneId.of("UTC+9")));
    Log.print("localTimeByClock: " + localTimeByClock);
  
    //通过ZoneId对象创建LocalTime对象,因为代码运行所在的时区为UTC+8, 所以localTimeById代
    //表的时间比localTime对应的时间要晚一个小时
    LocalTime localTimeById = LocalTime.now(ZoneId.of("UT+7"));
    Log.print("localTimeById: " + localTimeById);
}

输出结果:

localTime: 16:19:40.943196300
localTimeByClock: 17:19:40.968182600
localTimeById: 15:19:40.968182600

ofxxx()

同样,LocalTime也有多个ofxxx()方法,我们通过例子来看下其中的几个:

private void localTimeOf() {
    //时:分创建LocalTime对象
    LocalTime hM = LocalTime.of(14, 20);
    //时:分:秒创建LocalTime对象
    LocalTime hMS = LocalTime.of(14, 20, 30);
    //时:分:秒:纳秒创建LocalTime对象
    LocalTime hMSN = LocalTime.of(14, 20, 30, 5000_0000);
  
    //通过Instant 和ZoneId创建LocalTime对象
    LocalTime instantTime = LocalTime.ofInstant(Instant.now(), ZoneId.systemDefault());
    //通过指定经过多少秒创建LocalTime对象,比如60秒,那对象对应的时间就是:00:01
    LocalTime ofSecondOfDay = LocalTime.ofSecondOfDay(60);
    //从TemporalAccessor接口对象中解析出时间,如果该对象中没有时间信息则会抛出异常
    LocalTime from = LocalTime.from(LocalDateTime.now());
  
    Log.print("hM: " + hM + ", hMS: " + hMS + ", hMSN: " + hMSN
            + ", instantTime: " + instantTime
            + ", ofSecondOfDay: " + ofSecondOfDay
            + ", from: " + from
    );
}

输出结果:

hM: 14:20, hMS: 14:20:30, hMSN: 14:20:30.050, instantTime: 16:19:40.968182600, ofSecondOfDay: 00:01, from: 16:19:40.969182

运算

LocalTime也定义了对时、分、秒和毫秒的加减运算,同样对LocalTime的加减运算并不会改变对象本身,运算结果返回的是原对象的副本。

private void localTimeOperation() {
    LocalTime localTime = LocalTime.now();
    Log.print("localTime: " + localTime + ", plus hour: " + localTime.plusHours(1)
            + ", plus minute: " + localTime.plusMinutes(1)
            + ", plus second: " + localTime.plusSeconds(1)
            + ", plus nanos: " + localTime.plusNanos(1));

    Log.print("localTime: " + localTime + ", minus hour: " + localTime.minusHours(1)
            + ", minus minute: " + localTime.minusMinutes(1)
            + ", minus second" + localTime.minusSeconds(1)
            + ", minus nanos: " + localTime.minusNanos(1));
}

输出结果

localTime: 17:27:35.313468800, plus hour: 18:27:35.313468800, plus minute: 17:28:35.313468800, plus second: 17:27:36.313468800, plus nanos: 17:27:35.313468801
localTime: 17:27:35.313468800, minus hour: 16:27:35.313468800, minus minute: 17:26:35.313468800, minus second17:27:34.313468800, minus nanos: 17:27:35.313468799

格式化

可将LocalTime对象格格式化,也可将格式化的时间通过LocalTime.parse()方法将格式化的字符转换成LocalTime对象。

private void localTimeFormat() {
    LocalTime localTime = LocalTime.now();
    //将LocalTime格式化
    String formatTime = localTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
    //从格式化后的时间字符串解析为LocalTime对象
    LocalTime parsedTime = LocalTime.parse(formatTime);
    Log.print("formatTime: " + formatTime + ", parsedTime: " + parsedTime);
}

输出结果

formatTime: 16:19:41, parsedTime: 16:19:41

和LocalDate类似,LocalTime实例也有获取和替换时间属性(时、分、秒、纳秒)方法以及一些其他方法,这里就不展开,直接看个例子

private void localTimeOther() {
    LocalTime localTime = LocalTime.now();
    int hour= localTime.getHour();
    int minute = localTime.getMinute();
    int second = localTime.getSecond();
    int nanos = localTime.getNano();

    Log.print("localTime: " + localTime + ", hour: " + hour
            + ", minute: " + minute
            + ", second: " + second
            + ", nanos: " + nanos
    );

    Log.print("localTime: " + localTime + ", with hour: " + localTime.withHour(20)
            + ", with minute: " + localTime.withMinute(30)
            + ", with second: " + localTime.withSecond(30)
            + ", with nanos: " + localTime.withNano(30)
    );

}

输出结果:

localTime: 17:35:08.411439700, hour: 17, minute: 35, second: 8, nanos: 411439700
localTime: 17:35:08.411439700, with hour: 20:35:08.411439700, with minute: 17:30:08.411439700, with second: 17:35:30.411439700, with nanos: 17:35:08.000000030

LcalDateTime

? LocalDateTime是LocalDate和LocalTime的组合,从它的命名也能猜出它是用于表示日期和时间的,比如“2022-03-29 17:42:30.988799200”,同样LocalDateTime 也是一个不可变的日期时间对象。也可以通过LocalDateTime对象访问其日期和时间字段,比如年、月、日、时、分、秒。LocalDateTime也不存储时区信息,也就是说不能通过LocalDateTime对象获时区信息。如果想要包含时区的日期时间对象,那么可使用ZoneDateTime对象。

常见方法

now()

now()有三个重载方法,最终是通过ofInstant方法创建LocalDateTime对象。

private void localDateTime() {
    LocalDateTime localDateTime = LocalDateTime.now();
    Log.print("localDateTime: " + localDateTime);
  
    //通过Clock对象创建LocalDateTime对象,因为代码运行所在的时区为UTC+8, 所以localDateTimeByClock代
    //表的时间比localDateTime对应的时间要早一个小时
    LocalDateTime localDateTimeByClock = LocalDateTime.now(Clock.system(ZoneId.of("UTC+9")));
    Log.print("localDateTimeByClock: " + localDateTimeByClock);
  
    //通过ZoneId对象创建LocalTime对象,因为代码运行所在的时区为UTC+8, 所以localDateTimeById代
    //表的时间比localDateTime对应的时间要晚一个小时
    LocalDateTime localDateTimeById = LocalDateTime.now(ZoneId.of("UT+7"));
    Log.print("localTimeById: " + localDateTimeById);

}

输出结果:

localDateTime: 2022-03-29T17:47:34.988799200
localDateTimeByClock: 2022-03-29T18:47:35.026780500
localTimeById: 2022-03-29T16:47:35.026780500

对于上面的输出,在日期和时间之间存在字母T,这是因为LocalDateTime#toString()方法中在日期和时间加上了字母T

ofxxx()

同样,LocalDateTime也有多个ofxxx()方法,我们通过例子来看下其中的几个:

private void localDateTimeOf() {
    //通过指定年月日时分创建LocalDateTime对象
    //也可通过Month对象指定月份。比如:LocalDateTime.of(2022, Month.MARCH, 21, 14, 20);
    LocalDateTime yMDHM = LocalDateTime.of(2022, 3, 21, 14, 20);


    //通过指定年月日时分秒创建LocalDateTime对象
    LocalDateTime yMDHS = LocalDateTime.of(2022, 3, 21, 14, 20, 20);
    //通过指定年月日时分秒纳秒创建LocalDateTime对象
    LocalDateTime yMDHSN = LocalDateTime.of(2022, 3, 21, 14, 20, 20, 968182600);

    //通过Instant 和ZoneId创建LocalDateTime对象
    LocalDateTime instantDateTime = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
    Log.print("yMDHM: " + yMDHM + ", yMDHS: " + yMDHS
            + ", yMDHSN: " + yMDHSN
            + ", instantDateTime: " + instantDateTime
    );
}

输出结果:

yMDHM: 2022-03-21T14:20, yMDHS: 2022-03-21T14:20:20, yMDHSN: 2022-03-21T14:20:20.968182600, instantDateTime: 2022-03-29T17:47:35.027777700

格式化

private void localDateTimeFormat() {
    LocalDateTime localDateTime = LocalDateTime.now();
    //将LocalDateTime格式化
    String formatDateTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  
    //从格式化后的日期时间字符串解析为LocalDateTime对象,
    //这里要注意解析时的模式要和格式化时的模式一致,避免解析失败。
    LocalDateTime parsedDateTime = LocalDateTime.parse(formatDateTime, 
                                                       DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    Log.print("formatDateTime: " + formatDateTime + ", parsedTime: " + parsedDateTime);
}

输出结果:

formatDateTime: 2022-03-29 17:47:35, parsedDateTime: 2022-03-29T17:47:35

同样LocalDateTime也提供了访问和替换日期时间属性以及其他的一些方法,具体大家可查看源码学习,这里也不展开了。

转换

? 在对LocalDate、LocalTime和LoalDateTime有一定了解后,我们再来看下他们之间的转换。

LocalDate 与LocalDateTime之间的转换

LocalDate和LocalDateTime之间的转换实际上就是增加或减少一些属性;比如LocalDate对象转换成LocalDateTime,那就是在LocalDate对象的基础上增加时间信息,要实现这个功能可借助LocalDate#atTime()LocalDate.atStartOfDay()方法。对于LocalDateTime转换成LocaDate对象,那就更简单了,只要获取它的LocalDate类型变量就可以了。

/**
 * LocalDate与LocalDateTime之间的转换
 */
private void localDateLocalDateTime() {
    LocalDate localDate = LocalDate.now();
    //日期转换为LocalDateTime, atTime()有多个重载方法,作用都是转换成LocalDateTime对象。
    LocalDateTime atTime = localDate.atTime(10, 20, 30);
    //atStartOfDay()方法返回日期的起始时间的LocalDateTime对象
    LocalDateTime startOfDay = localDate.atStartOfDay();

    Log.print("localDate: " + localDate + ", atTime: " + atTime + ", startOfDay: " + startOfDay);

    LocalDateTime localDateTime = LocalDateTime.now();
    //toLocalDate方法获取LocalDateTime对象中的LocalDate类型变量date
    LocalDate ld = localDateTime.toLocalDate();
    Log.print("localDateTime: " + localDateTime + ", ld: " + ld);
}

输出结果

localDate: 2022-03-29, atTime: 2022-03-29T10:20:30, startOfDay: 2022-03-29T00:00
localDateTime: 2022-03-29T19:17:25.253960, ld: 2022-03-29

LocalTime 与LocalDateTime之间的转换

? LocalTime 与LocalDateTime之间的转换与上面的情况类似,LocalTime借LocalTime#atDate()方法转换成LocalDateTime对象;LocalDateTime获取其LocalTime类型属性即可。

/**
 * LocalTime与LocalDateTime之间的转换
 */
private void localTimeLocalDateTime() {
    LocalTime localTime = LocalTime.now();
    //通过LocalTime#atDate(LocalDate date)方法转换成LocalDateTime对象
    LocalDateTime localDateTime = localTime.atDate(LocalDate.now());
  
    //toLocalTime方法获取LocalDateTime对象中的LocaleTime类型变量time
    LocalTime lt = localDateTime.toLocalTime();
    Log.print("localDateTime: " + localDateTime + ", lt: " + lt);
}

输出结果

localDateTime: 2022-03-29T19:27:25.267052, lt: 19:27:25.267052

LocalDateTime 与时间戳之间的转换

? LocalDateTime与时间戳(从1970-01-01-00:00:00经过的时间)之间的转换需要借助Instant对象,且需要指定时区,因为LocalDateTime对象是没有存储时区信息。他们之间的转换需要注意:当把LocalDateTime通过指定的时区转换成时间戳之后,这个时间戳就和该时区关联了;如果再把转换后得到的时间戳转换为LocalDateTime,那就需要使用同样的时区,否则转换后得到的LocalDateTime和之前的所对应的日期时间就不一样了,这一点可以通过下面的例子得到验证。

/**
 * LocalDateTime与时间戳(从1970-01-01-00:00:00经过的时间)之间的转换
 */
private void localDateTimeMillis() {
    //创建ZoneOffset对象,这里指定的偏移时间为“+6”,即UTC+6
    ZoneOffset zoneOffset6 = ZoneOffset.of("+6");
    LocalDateTime localDateTime = LocalDateTime.now(zoneOffset6);
    Log.print("localDateTime: " + localDateTime);

    //将LocalDateTime对象转换为时间戳
    //将LocalDateTime转换成时间戳是要指定ZoneOffset/ZoneId, 要不然就没有意义了,
    //因为同一个日期时间但不同的时区,时间戳是不一样的。这里要注意转换得到的时间戳是关联了时区的,
    //所以如果你用这个转换后的时间戳采用用另一个时区转换成日期时间,那肯跟之前的LocalDateTime对象代表
    //的日期时间是不同的。
    long millis = localDateTime.toInstant(zoneOffset6).toEpochMilli();

    //创建ZoneOffset对象,这里指定的偏移时间为“+8”,即UTC+8
    ZoneOffset zoneOffset8 = ZoneOffset.of("+8");
    Instant instant = Instant.ofEpochMilli(millis);

    //采用与LocalDateTime转换为时间戳相同的ZoneOffset创建LocalDateTime对象
    LocalDateTime ldSameZoneOffset = LocalDateTime.ofInstant(instant, zoneOffset6);
    //上述ofInstant()是JDK11增加的方法,对于JDK1.8可以使用下面的方式
    //LocalDateTime ldSameZoneOffset = Instant.ofEpochMilli(millis).atZone(zoneOffset).toLocalDateTime();

    //将时间戳转换为LocalDateTime对象,但是这里指定的是zoneOffset8
    //所以ldDiffZoneOffset与前面的localDateTime代表的日期时间不一样。
    LocalDateTime ldDiffZoneOffset = LocalDateTime.ofInstant(instant, zoneOffset8);

    Log.print("instant millis: " + millis + ", ldSameZoneOffset: "
              + ldSameZoneOffset + ", ldDiffZoneOffset: " + ldDiffZoneOffset);

}

输出结果:

localDateTime: 2022-03-30T13:40:26.222052300
instant millis: 1648626026222, ldSameZoneOffset: 2022-03-30T13:40:26.222, ldDiffZoneOffset: 2022-03-30T15:40:26.222

如打印所示:ldSameZoneOffset采用的是和locaDateTime转换时间戳相同的ZoneOffset,所以得到的日期时间和localDateTime相同;而ldDiffZoneOffset采用的是和locaDateTime转换时间戳相同的ZoneOffset,所以得到的日期时间和localDateTime不同。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:11:18  更:2022-04-01 23:12:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:56:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码