相关文章推荐
任性的手电筒  ·  Finding Circular ...·  8 月前    · 
豪情万千的手链  ·  MySQL之——GROUP ...·  11 月前    · 

1 Instant

Instant 表示基于世界标准时间(UTC)的时间线上的某一个时间点,通常用作事件的时间戳。

Instant 取值为 基于世界标准时间 从 1970/01/01 00:00:00.000 到 某一个时间点 经历的时长(秒 + 纳秒),例如:

instantValue = 0s:表示 1970/01/01 00:00:00.000 (UTC) 或 1970/01/01 08:00:00.000 (UTC+8)

instantValue = 3600s:表示 1970/01/01 01:00:00.000 (UTC) 或 1970/01/01 09:00:00.000 (UTC+8)

// 获取当前时间点
Instant instant = Instant.now();
// 获取指定时间点(毫秒)
Instant instant = Instant.ofEpochMilli(long epochMilli);
// 获取指定时间点(秒)
Instant instant = Instant.ofEpochSecond(long epochSecond);
// 获取时间点值(毫秒)
long instantValue = instant.toEpochMilli();

注意: 当通过指定时间点的方式创建Instant对象时,参数值应该是基于世界标准时间的值。

2 ZoneId

ZoneId 表示时区,例如:北京时区为东八区,即 UTC+8 。

// 获取当前系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
// 获取指定时区:东八区
ZoneId zoneId = ZoneId.of("+08:00");

3 LocalDateTime

LocalDateTime 表示一个不含时区信息的时间,其组成包含两个部分:LocalDate 和 LocalTime

LocalDate 仅包含日期部分(即 年 月 日)

LocalTime 仅包含时间部分(即 时 分 秒)

通过1、2两节内容可知,要表示一个时间,需要 Instant 和 ZoneId 两个信息,即 基于世界标准时间的时间点 和 要表示的时间的时区 信息,这样,才可以计算得到一个相应的时间信息,例如:

instantValue = 3600s:表示 1970/01/01 01:00:00.000 (UTC)

zoneId = UTC+8:表示 东八区

localDateTime = 1970/01/01 01:00:00.000(UTC) + 时区偏移量(+8小时) = 1970/01/01 09:00:00.000 (UTC+8)

// 获取当前时间点
Instant instant = Instant.now();
// 获取当前系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
// 获取当前系统默认时区的本地时间
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
// 快捷方式:获取当前系统默认时区的本地时间
LocalDateTime nowLocalDateTime = LocalDateTime.now();

通过上述说明可知,LocalDateTime仅保存一个时间信息,在构造其对象时,提供的 Instant 和 ZoneId 信息,只是为了计算对应时区的一个时间信息,LocalDateTime 对象构造完成后,即表示一个时间,但并不保存时区信息。因此,也可以通过直接指定时间的方式构造 LocalDateTime 对象。

// 直接指定时间
LocalDateTime localDateTime = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);


由于 LocalDateTime 对象不保存时区信息,因此,就无法从其中获取 Instant 信息。因为没有时区信息,无法确定 LocalDateTime 表示的是哪里的时间,因此,无法确定对应的世界标准时间的时间点。例如:

1970年01月01日 16:00:00

只有一个时间信息,没有时区信息,无法知道这个时间是北京时间,还是纽约时间。

在实际应用过程中,LocalDateTime 对象通常用于时间格式化(显示时间),而不用于不同时区的时间转换。

4 ZonedDateTime

LocalDateTime 表示一个无时区信息的时间,而 ZonedDateTime 表示一个包含时区信息的时间。

当为 LocalDateTime 附上时区信息时,即可转化为 ZonedDateTime 对象。

// 表示 localDateTime 为 UTC+8 时区的时间  
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("+08:00"));

Instant 也是一个仅包含时间信息的对象,因此,为 Instant 附上时区信息时,同样,可转化为 ZonedDateTime 对象。

// 基于 UTC+8 时区,将 instant 转化为 ZonedDateTime 对象。
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("+08:00"));
// 等同于如下代码
ZonedDateTime zonedDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("+08:00")).atZone(ZoneId.of("+08:00"));

由于 ZonedDateTime 包含时区信息,因此,可以从其中获取 Instant 对象信息,例如:

1970年01月01日 16:00:00 UTC+8

明确是东八区的时间,则对应的世界标准时间为 1970年01月01日 08:00:00 ,其 instantValue = 28800秒。

// 时区
ZoneId zoneId = zonedDateTime.getZone();
// 时间点
Instant instant = zonedDateTime.toInstant();
// 世界标准时间的时间点值
long timestamp = zonedDateTime.toInstant().toEpochMilli();

5 关系图解

上图描述了 Instant、ZoneId、LocalDateTime 和 ZonedDateTime 之间的关系。

需要说明的是,Instant 和 ZoneId 结合得到 LocalDateTime 步骤中,ZoneId 仅用于确定时间偏移量,从而计算得到该时区对应的时间,并由 LocalDateTime 对象保存时间信息,而时区信息并没有在 LocalDateTime 对象保存。

常见的时间异常情况,大部分是由于时区问题没有处理正确导致。这种情况,在网络传递时间数据的时候,时常发生,其根本原因是两端基于不同的时区对时间进行处理,例如:

服务端:基于UTC,返回时间字符串信息,如 timestamp = 1970/01/01 08:00:00,对应北京时间为 1970/01/01 16:00:00。

客户端:基于本地时区,处理服务端返回的时间字符串信息,即 将 1970/01/01 08:00:00 当成北京时间,导致时间差8小时。

6 时间格式化

在 Java 8 之前,通常使用 SimpleDateFormat 对时间进行格式化,但 SimpleDateFormat 不是线程安全的类,即 在多线程环境下使用共享的 SimpleDateFormat 对象(例如 static 对象),则可能发生异常情况。

因此,为了保证线程安全,在每个线程中,需要创建一个 SimpleDateFormat 对象,保证不同线程之间不会共享一个 SimpleDateFormat 对象。或者,通过 ThreadLocal 方式,达到线程隔离效果。

在 Java 8 之后,JDK 提供了 DateTimeFormatter 类,用于提供时间格式化方法。

// 初始化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 获取 当前系统默认时区 的 本地时间
LocalDateTime nowDateTime = LocalDateTime.now();
// 格式化时间
String dateTimeString = formatter.format(nowDateTime);
// 解析 时间字符串 得到 LocalDateTime 对象
LocalDateTime dateTimeObj = LocalDateTime.from(formatter.parse(dateTimeString));

7 相关文章

《字符串格式化:Formatter类》

import java .text.ParseException; import java .text.Simple Date Format ; import java .util.Locale; import java .util.regex.Pattern; public class Format Trans format ion { public static void main(String[] args) throws ParseExc DateTime Format ter dateTime Format ter = DateTime Format ter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"); Local DateTime now = LocalDa Date Format java .text. Date Format Date Format 提供了很多类方法,以获得基于默认或给定语言环境和多种 格式化 风格的默认 日期 / 时间 Format ter。 格式化 风格包括 FULL、LONG、MEDIUM 和 SHORT。方法描述中提供了使用这些风格的更多细节和示例。 Date Format 可帮助进行 格式化 并解析任何语言环境的 日期 。对于月、星期, public class Deal Date Format Util { public static String deal Date (String old Date Str) throws ParseException { Date Format df = new Simple Date Format ("yyyy-MM-dd'T'HH:mm:ss"); Date date = df.parse(o... 1、获取今天的 日期 2、指定 日期 ,进行相应操作3、生日检查或者账单日检查4、获取当前的 时间 5、 日期 前后比较6、处理不同时区的 时间 7、比较两个 日期 之前 时间 差8、 日期 时间 格式 解析、 格式化 9、 java 8 时间 类与 Date 类的相互转化在 Java 8 以前, 日期 时间 处理一直被广大 java 程序员抱怨太难用,首先是和中,都包含类,如果要进行 时间 格式化 ,还需要类处理。同时中既包含了 日期 ,又包含了 时间 ,所以 java 8 新的 日期 时间 库,很好的解决了以前 日期 时间 类的很多弊端。并且也借鉴了第三方 日期 库很多的优点。在 最近在开发项目过程中,发现返回的数据中现实的 日期 与数据库中 日期 大概相差8小时,这是因为直接从数据库中查询出来的 时间 是格林威治 时间 ,而不是北京(东八区) 时间 ,所以我们需要做 日期 格式化 ,将格林威治 时间 转为北京 时间 ,代码如下: @Json Format ( shape = Json Format .Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss",... 在 Java 8之前,我们使用Simple Date Format Date Format 类来表示一种 格式 ,这存在很多问题,例如它们笨重,易变且不是线程安全的,这意味着无法共享它们,并且每次都需要要将String转换为 Date ,必须创建一个新的 Date Format 对象。 尽管将Simple Date Format 封装到线程局部变量中确实可以缓解,但这还不够。 JDK 8在新的 DateTime Format ter类中解决了该问题,该类可用于定义 日期 时间 格式 ,例如“ yyyy-MM-dd HH:mm:SS”,用于指定 Java 8之前的版本, 格式化 日期 常使用Simple Date Format ,但这个类并不是线程安全的,通常要用作局部变量或者使用ThreadLocal包装。或者使用额外的joda time 依赖来对 日期 进行操作。 但是到了 Java 8,这类烦恼都没有了,全新的 日期 api可以快速实现 日期 格式化 。 1. 日期 格式化 - 日期 类型的字符串转换成其他形式 * 不带时分秒的 日期 字符串转化 我们大家在初学 java 时,经常会做一些练习,这些练习往往会伴随着 日期 的相关数据,下面几种方法是 日期 数据的几种设置 public class demo2 { public static void main(String[] args) { //Calendar类是一个单例模式的类,他的构造方法私有且不可被实例化 //get Inst ance是类内部的一个静态方法,用来返回当前实例 Cal... 原标题: Java 中的 日期 时间 格式化 1 Java 日期 时间 格式化 的概念我们在日常的开发过程中常常会碰到关于 日期 时间 的计算与存储问题,比如我们要把一个当前 时间 类型转换成字符串类型,我们会直接使用Util包下的 Date 数据类型( java .util. Date )来创建 时间 对象,例如: Date date = new Date ();但如果我们对其对象进行打印会发现 时间 的数据值如下:Fri Jul 24 16:02:... java .sql. Date 日期 格式 为:年月日 java .sql. Time 日期 格式 为:时分秒 java .sql. Time stamp 日期 格式 为:年月日时分秒纳秒(毫微秒) 从数据库中取出来的 日期 一般都用getTi...