Java 8以前日期API相关问题及时间和时区介绍:GMT与UTC
一、Java 8 以前日期API相关问题
Java 8 以前,java.util.Date,java.util.,
java.util.,
java.text.这四个类分别用于处理日期、日历、公历、时间格式化
缺点:
Java 8 重新设计了所有日期时间、日历及相关时区的API,统一放置在java.time包下,并作出如下改进
二、时间和时区1. GMT和UTC
GMT:格林尼治标准时间,也就是世界时。GMT的正午是指当太阳横穿格林尼治子午线(本初子午线)时的时间。但由于地球自转不均匀不规则,导致GMT不精确,现在已经不再作为世界标准时间使用
UTC:协调世界时。是经过平均太阳时(以格林威治时间 GMT 为准)、地轴运动修正后的新时标,以「秒」为单位的国际原子时所综合精算而成的时间。为确保UTC与GMT相差不会超过0.9秒,在有需要的情况下(例如 1998-12-31T23:59:60Z )会在UTC内加上正或负闰秒。协调世界时区会使用 “Z” 来表示,协调世界时也会被称为 “Zulu time”。UTC现在作为世界标准时间使用。
即:UTC与GMT基本上等同,误差不超过0.9秒。不过日常使用中,GMT 与 UTC 的功能与精确度是没有差别的。
2. 时区
时区作为地理概念,表示 “遵守统一时间标准的一个地区”。
使用与 UTC 的偏移来表示时区,例如:中国所在时区为 UTC+08:00(又称为 Time,即 “中国标准时间”)
地球自西向东旋转,东边比西边先看到太阳,东边的时间也比西边的早。为了统一世界的时间,1884年的国际经度会议规规定将全球划分为24个时区(东、西各12个时区)。规定英国(格林尼治天文台旧址)为零时区(基准 UTC),东1-12区,西1-12区,中国北京处于东8区(UTC+08:00),那么我们的时间会领先基准-也就是我们在早上 9 点时,伦敦是早上 1 点。
3. Unix时间戳
自 1970-01-01T00:00:00Z (Z 即表示 UTC 时间)至今的毫秒差作为表示时间的数值,并且移除期间的“闰秒”(例如 1998-12-31T23:59:60Z ),这么做当然是为了简化计算机对时间操作的复杂度。Unix 时间体系中,每天固定 86400 秒。
4. Java中的Unix时间
Java 确保:每天 24 小时、每小时 60 分、每分钟 60 秒。
Java 中获取 “当前” 时间的方法,其底层实现,全部由
java.lang..() 提供自 UTC 1970-01-01T00:00:00 的毫秒数。
java.lang..() 作为 方法,其实现与 JVM 所在的机器相关(通常使用 NTP 协议保持更新)。
三、Java8相关类1. 、、
特点:不包含时区信息,与转换时必须提供时区信息
获取对象方法:
获取相关参数方法:
判断相关方法:
增加相关的方法
减少相关方法:
指定年月日方法:
字符串相关方法
2. 时间调节器
前面看到的所有日期操作都是相对比较直接的。有的时候,你需要进行一些更加灵活复杂的操作,比如,将日期调整到下个周日、下个工作日,或者是本月的最后一天。这时,就需要时间调节器 ,可以更加灵活地处理日期。
3. 计算两个“时间”间隔类
表示一个时间段, 包含两部分: 表示秒,nanos 表示纳秒,它们的组合表达了时间长度。
注意, 不包含毫秒这个属性。
只能处理 , , ; 如果传入的是 ,将会抛出异常
常用API:
4. 计算两个日期间隔类
在概念上和 类似,区别在于 是以年月日来衡量一个时间段。 用于计算两个时间间隔, 用于计算两个日期间隔,所以 () 方法只能接收 类型的参数。
5. 时间戳类
java.time. 时间线上的一个瞬时点,承载纳秒级精度的 Unix 时间戳,其 () 方法基于 ISO-8601 进行格式化。 不承载时区信息。
get系列的方法
系列方法
6. Clock 时钟系统
Clock 是时钟系统,用于查找当前时刻。你可以用它来获取某个时区下当前的日期或者时间。可以用 Clock 来替代旧的
.() 与 .() 方法。
7. 、、 带时区的日期时间
三个类方法及用法和 、 、 基本一样,只不过、、 这三个 带有特定时区
8. 世界时区类
Java 使用 来标识不同的时区。时区从基准 UTC 开始的一个固定偏移。 的子类 ,代表了这种从伦敦格林威治零度子午线开始的时间偏移,也就是时差。
常用API:
9. 用于解析日期字符串和格式化日期输出
用于解析日期字符串和格式化日期输出,创建格式化器最简单的方法是通过 的静态工厂方法以及常量。
常用API:
格式化输出& 字符串解析

java.time.. 能够进行 类型(包括:、、、)的格式化输出。同时,、、、 提供了静态的 parse 方法,能够进行字符串解析
四、Date类相关转换问题1. 与相互转换
Date date = Date.from(instant);
Instant instant2 = date.toInstant();
复制代码
2. 与相互转换
LocalDateTime localDateTime1 = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
复制代码
3. 与相互转换4. 与相互转换5. 与相互转换6. 格式化 使用方法:
/* 1.在需要执行格式化的地方都新建SimpleDateFormat实例,使用局部变量来存放SimpleDateFormat实例
缺点:可能会导致短期内创建大量的SimpleDateFormat实例
*/
public static String formatDate(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
/* 2.把SimpleDateFormat实例设为静态成员变量,共享SimpleDateFormat对象
缺点:需要对SimpleDateFormat添加同步
*/
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static String formatDate(Date date) {
synchronized (sdf) {
return sdf.format(date);
}
}
/* 3.使用ThreadLocal来限制SimpleDateFormat只能在线程内共享,这样就避免了多线程导致的线程安全问题
*/
private static ThreadLocal threadLocal = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
public static String formatDate(Date date) {
return threadLocal.get().format(date);
}
复制代码
五、java.time类图

类图所示,java.time. 提供的接口:
、、、、:实现 与 接口 、:实现 接口
六、总结1.Java 8时间日期 API 中的设计模式
这里设计模式与标准的教科书式的设计模式可能有所区别,所以我们在使用设计模式时也应灵活处理,不是一成不变的。
2. Java 8的日期时间API总结
新的时间与日期 API 中很重要的一点是,它定义清楚了基本的时间与日期的概念,比方说日期、时间、瞬时时间、持续时间、时区及时间段。它们都是基于 日历系统,它是世界民用历法,也就是我们所说的公历。
java.time包下主要包含下面几个主要的类:
:表示不带时间的日期,比如:2016-10-20 :表示不带日期的时间,比如:23:12:10 :日期时间,比如:2016-10-20 23:14:21 : 时间调节器 :获得指定日期时间等,如当月的第一天、今年的最后一天等 :持续时间,计算两个“时间”的间隔 :日期间隔,计算两个“日期”的间隔 :Unix 时间,它代表的是时间戳,比如 2018-01-14T02:20:13.592Z Clock:时钟,获取某个时区下的瞬时时间 :时区id,例如 Asia/等 :带时区的日期时间 :时间格式化
新的 API 区分各种日期时间概念并且各个概念使用相似的方法定义模式,这种相似性非常有利于 API 的学习。总结一下一般的方法规律:
of:静态工厂方法,用于创建实例 now:静态工厂方法,用当前时间创建实例 parse:静态工厂方法,从字符串解析得到对象实例 get:获取对象的部分状态 is:检查某些东西的是否是 true,例如比较时间前后 with:返回一个部分状态改变了的时间日期对象拷贝(单独一个with方法,参数为类型) plus:返回一个时间增加了的时间日期对象拷贝 minus:返回一个时间减少了的时间日期对象拷贝 to:把当前时间日期对象转换成另外一个,可能会损失部分状态。 at:把这个对象与另一个对象组合起来,例如:date.(time) :将时间日期格式化为字符串 最后再次声明,Java 8 中新的时间与日期 API 中的所有类都是不可变且线程安全的,任何修改操作都会返回一个新的实例,而之前 java.util.Date、 以及 这些关键的类都不是线程安全的。
























