一、基本概念
1、格林威治時(shí)間(GWT)
格林威治子午線上的地方時(shí),位于倫敦郊區(qū)的皇家格林尼治天文臺(tái)的標(biāo)準(zhǔn)時(shí)間,也叫世界時(shí)。比如我們中國(guó)是東八區(qū),北京時(shí)間是(GMT+08:00)
2、協(xié)調(diào)世界時(shí)間(UTC)
UTC是根據(jù)原子鐘來計(jì)算時(shí)間,現(xiàn)在世界上最精確的原子鐘50億年才會(huì)誤差1秒,可以說非常精確。
3、北京時(shí)間(CST)
中國(guó)時(shí)間的標(biāo)準(zhǔn)。
4、太平洋時(shí)間(PST)
是在美國(guó)、加拿大、墨西哥西海岸靠近太平洋的地區(qū)使用,也被稱為太平洋時(shí)區(qū)。
相比較而言:個(gè)人理解 UTC 是標(biāo)準(zhǔn)時(shí)間參照,GMT(格林威治時(shí)間)、CST(北京時(shí)間)、PST(太平洋時(shí)間)等等是具體的時(shí)區(qū)。因?yàn)镚MT是根據(jù)地球的自轉(zhuǎn)和公轉(zhuǎn)來計(jì)算時(shí)間,而地球的自轉(zhuǎn)正在緩速變慢,所以使用GMT的話,總有一天,打個(gè)比方,中午12點(diǎn),并不是一天太陽(yáng)當(dāng)頭照的時(shí)候,很可能就是早上或者晚上了。所以說UTC更加精確。
二、夏令時(shí)
是一種為節(jié)約能源而人為規(guī)定地方時(shí)間的制度。也叫夏時(shí)制,夏時(shí)令(Daylight Saving Time:DST),又稱“日光節(jié)約時(shí)制”和“夏令時(shí)間”,在這一制度實(shí)行期間所采用的統(tǒng)一時(shí)間稱為“夏令時(shí)間”。一般在天亮早的夏季人為將時(shí)間調(diào)快一小時(shí),可以使人早起早睡,減少照明量,以充分利用光照資源,從而節(jié)約照明用電。各個(gè)采納夏時(shí)制的國(guó)家具體規(guī)定不同。目前全世界有近110個(gè)國(guó)家每年要實(shí)行夏令時(shí)。
據(jù)稱最早有夏令時(shí)構(gòu)思的是本杰明·富蘭克林
三、時(shí)區(qū)的處理:
服務(wù)器時(shí)間是東八區(qū)時(shí)間,前端頁(yè)面會(huì)在全世界各地時(shí)區(qū)。
為兼容世界各地時(shí)間,需要:
- 1.服務(wù)器拉取的北京時(shí)間轉(zhuǎn)為本地時(shí)區(qū)的時(shí)間。
- 2.將用戶本地時(shí)間轉(zhuǎn)換為北京時(shí)間傳給服務(wù)器。
公式:都轉(zhuǎn)換成零時(shí)區(qū)的時(shí)間(UTC時(shí)間)
其他時(shí)區(qū)時(shí)間 + 其他時(shí)區(qū)時(shí)差 = 本地時(shí)間 + 本地時(shí)差 = UTC時(shí)間 = GWT時(shí)間
JS & Javascript代碼:
/**
* 判斷是否為夏令時(shí)
* @param date
* @returns {boolean}
*/
function isSummerTime(date) {
const springTime = new Date(date.getFullYear(), 0, 1);
const summerTime = new Date(date.getFullYear(), 6, 1);
if (springTime.getTimezoneOffset()
=== summerTime.getTimezoneOffset()
=== date.getTimezoneOffset()) {
return false;
} else {
return true;
}
}
/**
* 北京時(shí)間轉(zhuǎn)本地時(shí)間
*/
function getLocalDate(east8date) {
const targetTimezone = -8;
const dif = new Date().getTimezoneOffset();
let localTime = east8date.getTime()
+ (targetTimezone * 60 * 60 * 1000) - dif * 60 * 1000;
localTime -= (isSummerTime(east8date) ? 60 * 60 * 1000 : 0);
return new Date(localTime);
}
/**
* 本地時(shí)間轉(zhuǎn)北京時(shí)間
*/
function getEast8Date(date) {
const targetTimezone = -8;
const dif = new Date().getTimezoneOffset();
let east8time = date.getTime() + dif * 60 * 1000
- (targetTimezone * 60 * 60 * 1000);
east8time += (isSummerTime(date) ? 60 * 60 * 1000 : 0);
return new Date(east8time);
}
Java代碼:
/**
* 系統(tǒng)時(shí)區(qū)時(shí)間轉(zhuǎn)成北京時(shí)區(qū)的時(shí)間發(fā)給云端
* 云端獲取的北京時(shí)區(qū)時(shí)間轉(zhuǎn)成系統(tǒng)時(shí)區(qū)的時(shí)間顯示
*/
public static Calendar timeZoneToCalendar(Calendar calendar,cboolean toBeijingOrLocal) {
int timeOffset;
if (toBeijingOrLocal) {
timeOffset = TimeZone.getDefault().getOffset(System.currentTimeMillis())
- TimeZone.getTimeZone("GMT+08").getRawOffset();
} else {
timeOffset = TimeZone.getTimeZone("GMT+08").getRawOffset()
- TimeZone.getDefault().getOffset(System.currentTimeMillis());
}
Calendar zoneCalendar = Calendar.getInstance();
long timeInMilis = calendar.getTimeInMillis() - timeOffset;
zoneCalendar.setTimeInMillis(timeInMilis);
return zoneCalendar;
}
四、夏令時(shí)實(shí)行國(guó)家:
1. 國(guó)內(nèi):
從1986年到1991年的六個(gè)年度,在全國(guó)范圍內(nèi)實(shí)行夏時(shí)制,1992年起,夏令時(shí)暫停實(shí)行。
2.國(guó)際:
- 俄羅斯
2011-2014使用夏令時(shí)
- 美國(guó)
美國(guó)夏時(shí)制的實(shí)行與否,完全由各州、各縣自行決定,不由聯(lián)邦政府統(tǒng)一規(guī)定。目前美國(guó)絕大部分地區(qū)實(shí)行夏令時(shí)。
- 歐盟國(guó)家
歐盟國(guó)家和瑞士都是從3月最后一個(gè)星期日到10月最后一個(gè)星期日實(shí)行夏令時(shí)。
- 加拿大
加拿大從3月第二個(gè)星期日到11月第一個(gè)星期日實(shí)行夏令時(shí),不過薩斯喀徹溫省大部分地區(qū)不實(shí)行。
- 墨西哥
墨西哥從4月第一個(gè)星期日到10月最后一個(gè)星期日實(shí)行夏令時(shí),不過在首都墨西哥城,由于市長(zhǎng)不同意總統(tǒng)實(shí)行夏令時(shí)的決定,有的區(qū)服從總統(tǒng)實(shí)行夏令時(shí),有的區(qū)則服從市長(zhǎng)不實(shí)行夏令時(shí)。
- 新西蘭
新西蘭由于處于南半球,所以夏季和北半球相反。它從9月最后一個(gè)星期日到4月第一個(gè)星期天實(shí)行夏時(shí)。
- 澳大利亞
澳大利亞除北部地區(qū)、昆士蘭州和西澳(佩斯、珀斯)之外全部實(shí)行夏令時(shí)。