Java 中的时间
# Java 中的时间
在计算机中,我们需要频繁地处理日期和时间,本文我们就来讲讲 Java 提供的时间 API。
在继续学习 Java 提供的时间 API 之前,读者应该对计算机中的时间有基本的认识,请参考:简单聊聊计算机之中的时间 (opens new window)
# 简单介绍
这里简单介绍下关于时间的一些术语:
- 日期:例如 2022 年 12 月 21 日,就是一个日期
- 时间:我们平时说的时间,可能是不带日期的,例如 12:00;也可能是带时间的,例如今日凌晨 3 点
- 时区:上一点我们说的时间,其实是本地时间,也就是本地时区的时间。在同一时刻,不同时区内的时间是不同的。
- 时刻:和时区无关的、唯一确定的一个时刻。假如一个人说现在是 8.30 分,并且不说在那个时区的话,我们是无法确定到底是什么时间的,因为说的人可能在其他时区。
为了精确的表示某一个时刻,我们需要给本地时间加上一个时区,例如以 GMT
或者 UTC
加时区偏移:GMT+08:00
或者 UTC+08:00
表示东八区。
GMT 表示格林尼治时间 (Greenwich Mean Time) ,就是世界时。
UTC 全称 Coordinated Universal Time,就是协调世界时。
两者的区别请看:简单聊聊计算机之中的时间 (opens new window)
其他表示时区的方式:
- 使用洲/城市来表示时区,例如
Asia/Shanghai
,表示上海所在地的时区。特别注意城市名称不是任意的城市,而是由国际标准组织规定的城市。 - 英文缩写,例如,
CST
表示China Standard Time
,也就是中国标准时间。但是CST
也可以表示美国中部时间Central Standard Time USA
,因此,缩写容易产生混淆,我们尽量不要使用缩写。
时区并不麻烦,麻烦的是夏令时。所谓夏令时,就是夏天开始的时候,把时间往后拨 1 小时,夏天结束的时候,再把时间往前拨 1 小时。我们国家实行过一段时间夏令时,1992 年就废除了,但是矫情的美国人到现在还在使用,所以时间换算更加复杂。
--引自廖雪峰的博客,这里不展开,比较少遇到,知道这么个东西就行
# 时间在计算机中的存储
计算机里存储的只是 0 和 1,那么时间是怎么存储的呢?其实计算机里的时间,存储的是一个整数,我们称为 Epoch Time
,也叫时间戳,其值是从 1970 年 1 月 1 日零点(格林威治时区/GMT+00:00)到现在所经历的秒数。
那么怎么转换成我们看到的时间呢?根据秒数来计算过了多少天,小时和分秒,然后根据时区来调整展示的时间。
类似 Excel 中,一个单元格存储的只是数字,其显示的格式,我们是可以定义的:例如显示为小数,时间等等,我们可以通过自定义格式来展示这个数字。
举个例子:假设目前存储的秒数是 1574208900
,表示从 1970 年 1 月 1 日零点 GMT 时区到该时刻一共经历了 1574208900 秒,当需要显示为某一地区的当地时间,就根据时区来调整。例如换算成伦敦、北京和纽约时间分别是:
1574208900 = 北京时间2019-11-20 8:15:00
= 伦敦时间2019-11-20 0:15:00
= 纽约时间2019-11-19 19:15:00
2
3
另外,不同地方的时间展示是不同的。例如国外常用的顺序为 月份/日期/年份,11/30/2016; 国内常用的顺序为年月日,如 2022-12-21。
# 时间戳
在不同的编程语言中,时间戳会有几种存储方式:
- 以秒为单位的整数:1574208900,缺点是精度只能到秒;
- 以毫秒为单位的整数:1574208900123,最后 3 位表示毫秒数;
- 以秒为单位的浮点数:1574208900.123,小数点后面表示零点几秒。
在 Java 中,使用的是 long 来存储 Epoch Time
(毫秒)。
要获取当前时间戳,可以使用 System.currentTimeMillis()
。
我们来练习下:
long time = System.currentTimeMillis();
System.out.println(time);
2
编译和运行(笔者练习的时候,时间是北京时间 2022 年 12 月 21 日 20:17 分左右):
1671624981335
补充知识点:
- 1970 年 1 月 1 日 是 unix 发明的时间,所以计算机中的时间从此开始。
# Java 提供的 API
Java 标准库有两套处理日期和时间的 API:
- 一套定义在
java.util
,主要包括Date
、Calendar
和TimeZone
这几个类,较为老旧,在 1.1 就出现了,不太好用 - 一套定义在
java.time
,主要包括LocalDateTime
、ZonedDateTime
、ZoneId
等。在 Java 8 引入。
我们可以看看 Java 的官方 API 文档,例如 Date 的:Date (Java Platform SE 8 ) (opens new window) ,可以看到很多都是被标注为已过时(Deprecated)。但一些老旧的系统使用的是旧的 API,所以我们有一定的必要简单了解下旧的。