Java currentTimeMillis()方法介绍
一、官方文档
参考自Java SE 8官方文档:
方法功能:返回从1970年1月1日午夜(UTC)开始到当前时间的毫秒值.
其中,需要特别说明的地方
1.午夜(midnight)指的时间是 0时0分0秒,UTC表示该时间是0时区的时间
2.当前时间,不是指我们北京时间(UTC+8,东八区)的当前时间,而是0时区的当前时间。
例如,你现在的时间是1970-01-01 08:00:01(UTC+8),此刻0时区的时间是1970-01-01 00:00:01(UTC),共经过了1秒,所以计算机中存储的毫秒值是1000。
二、时间表示的起源及2038年问题
UNIX系统把1970年1月1日 00:00:00 GMT(GMT也表示0时区含义)作为时间的开始,称为纪元。
当时,操作系统是32位的,综合考虑决定使用32位的有符号数存储时间。对于1970年1月1日 00:00:00 UTC (等价我们的时间1970年1月1日 08:00:00 UTC+8)在计算机中存储为0。
注意,在UNIX中存储的值的单位是秒,在Java编程语言中的值的单位是毫秒。
用32位有符号能表示的最大值是01111111 11111111 11111111 11111111, 即214748367, 对应UTC时间2038年1月19日3时14分7秒。过了这个时间点,时间会溢出并变成10000000 00000000 00000000 00000000,即-214748368,对应的UTC时间1901年12月13日20时45分52秒,这样便会出现时间回归的现象,很多软件便会运行异常了。
要解决这个问题,最简单的方式是扩展UNIX时间的长度,用64位数字来表示它。64位二进制数的实际可用位数是63位。最大表示到公历的UTC时间292277026596年12月4日。如果那个时候人类文明还存在的话。公元纪年很可能已经因为太难用而被抛弃了。理想的情况是到2038年, 64位系统已经成为主流,从而避免特意去修正这个问题所需要的大量开销。否则,人们就必须把新的64位时间拆分成两部分并分别保存在两个变量里,这是一个麻烦而且效率低下的选择。
许多操作系统和编程语言都是以Unix为基础的,因此时间的起点,纪元通常和Unix选定的1970年1月1日 00:00:00 GMT一致。
三、Java中时间的表示
文章最开始就提到:时间是从1970年1月1日午夜(UTC)开始到当前时间的毫秒值。
Java中使用java.util.Date
保存该毫秒值。
使用指定的long类型的毫秒值作为参数,初始化Date对象
默认构造函数使用当前时间的毫秒值初始化Date对象
另外,我们可以看到返回值是long类型,在Java中毫秒值是用64位存储的,不存在2038年的问题。
第一点,对于1970-01-01 00:00:01(UTC),毫秒值应该是1000,那么Java的实际存储值是1000吗?让我们来做个实验吧。
public static void main( String[] args ) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
// 设置时区0时区
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String source = "1970-01-01 00:00:01";
Date data = sdf.parse(source);
System.out.println("0时区时间:" + source +", 保存的毫秒值:" + data.getTime());
}
运行结果,和我们期待的一样:
第二点,我们的东八区北京时间1970-01-01 08:00:01(UTC+8),存储值也是1000吗?注意,这里的时间是8小时0分1秒
public static void main( String[] args ) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
// 设置时区为东八区
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
String source = "1970-01-01 08:00:01";
Date data = sdf.parse(source);
System.out.println("东八区时间:" + source +", 保存的毫秒值:" + data.getTime());
}
}
运行结果如下图所示,验证了当前时间是指0时区的时间。
第三点,对于2038年1月19日3时14分7秒(UTC),在UNIX32位系统中保存为int的最大值214748367(秒),那么在Java的64位long类型中保存的值是214748367 * 1000 = 2147483671000毫秒吗?
public static void main( String[] args ) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
// 设置时区0时区
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
String source = "2038-01-19 03:14:07";
Date data = sdf.parse(source);
System.out.println("0时区时间:" + source +", 保存的毫秒值:" + data.getTime());
System.out.println("int最大值*1000:" + (long)Integer.MAX_VALUE * 1000);
}
运行结果,也和我们期待的一致
参考文章列表: 【[关于1970-1-1 00:00.000的知识](https://blog.csdn.net/tianzizhi/article/details/4547373) 】
更多推荐
所有评论(0)