今天看别人代码的时候,两次发现了时间常数2208988800,服务端加上这个常数,客户端又减去这个常数。不明白为什么有这个常数,于是搜索了下。
原来时间服务提供的是从1900年1月1号零时零分零秒(即午夜)到当前的秒数(GMT),而我们在Java编码中经常打交道的时间是从从1970年1月1号零时零分零秒到当前的秒数(或者毫秒数)GMT,而2208988800这个常数就是指从1900年1月1号零时零分零秒(即午夜)到1970年1月1号零时零分零秒的秒数GMT。
例如,RFC 868中出现了这个常数https://www.rfc-editor.org/rfc/rfc868.html:
RFC 5905中出现了这个常数https://www.rfc-editor.org/rfc/rfc5905.html:
代码示例:
package com.thb;
import java.util.Date;
/**
* 模拟了时间服务的服务侧、接收侧的时间计算部分
* 时间服务可以参考RFC 868、RFC 5905
* @author Administrator
*
*/
public class Test1 {
public static void main(String[] args) {
// 常数等于从1900年1月1号零时零分零秒(即午夜)到1970年1月1号零时零分零秒的秒数(GMT)
Long timeDifference = 2208988800L;
System.out.println("int最大值(带符号): " + Integer.MAX_VALUE);
// 服务侧计算时间
System.out.println("-----------服务侧时间计算-----------");
/*
* 从1900年1月1号零时零分零秒(即午夜)到当前的秒数(GMT), 等于下面两项相加:
* 1)从1900年1月1号零时零分零秒(即午夜)到1970年1月1号零时零分零秒的秒数GMT
* 这个值就等于2208988800
* 2)从1970年1月1号零时零分零秒到当前的秒数GMT,这个值就等于System.currentTimeMillis() / 1000L
*/
Long longTime = System.currentTimeMillis() / 1000L + timeDifference;
System.out.println("从1900年1月1日零分零秒到目前的秒数: " + longTime);
// 服务侧传输给接收侧用32位二进制数字,所以下面转化为int型
int intTime = (int)(System.currentTimeMillis() / 1000L + timeDifference);
System.out.println("intTime: " + intTime);
System.out.println();
System.out.println("-----------接收侧时间计算-----------");
// 接收侧计算时间
// 将接收到的秒数转化为无符号的数
Long receivedLongTime = Integer.toUnsignedLong(intTime);
System.out.println("receivedLongTime: " + receivedLongTime);
/*
* 跟服务侧的计算逆着
* 用收到的秒数减去:从1900年1月1号零时零分零秒(即午夜)到1970年1月1号零时零分零秒的秒数GMT
* 结果就是从1970年1月1号零时零分零秒到当前的秒数
* new Date(long date)中的输入参数要求是从1970年1月1号零时零分零秒到当前的毫秒数
*/
Date date = new Date((receivedLongTime - timeDifference) * 1000L);
System.out.println("还原后的当前时间: " + date);
}
}
一次运行的输出: