Java中的时间
# 50.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,所以我们有一定的必要简单了解下旧的。