
坑~夏令時(shí)冬令時(shí)引發(fā)的時(shí)間換算問(wèn)題
起因
最近接觸到?些國(guó)外的項(xiàng)?,由于國(guó)內(nèi)外有時(shí)差這個(gè)東西,對(duì)于某些基礎(chǔ)數(shù)據(jù)存到數(shù)據(jù)庫(kù)的時(shí)候需要記錄時(shí)間,為了?便,這?采?了時(shí)間戳(int或者timestamp)記錄。由于時(shí)間戳全球都是?樣的,需要的時(shí)候根據(jù)時(shí)區(qū)進(jìn)?轉(zhuǎn)換就能夠拿到當(dāng)?shù)氐臅r(shí)間。
嗯~ o(* ̄▽ ̄*)o,這樣看起來(lái)確實(shí)沒(méi)什么?病。眾所周知,?天有24?時(shí),換算成秒就是:24*60*60=86400秒。
然?,我在某次使? MySql 的FROM_UNIXTIME發(fā)現(xiàn)?個(gè)問(wèn)題,兩個(gè)時(shí)間相差86400秒,但是格式化之后卻不是相差?天
假設(shè)北京時(shí)間2019年11?25? 12:00:00,對(duì)應(yīng)的時(shí)間戳是:1574654400,照理說(shuō)這個(gè)時(shí)間戳加上?天86400秒,理論上就是北京時(shí)間2019年11?26? 12:00:00,事實(shí)上確實(shí)如此,國(guó)內(nèi)的話這么算確實(shí)沒(méi)什么問(wèn)題,但是如果是國(guó)外時(shí)區(qū)的話,那可能會(huì)出問(wèn)題。
由于國(guó)外部分國(guó)家有夏令時(shí)和冬令時(shí)之分(具體下?會(huì)細(xì)說(shuō)),直接加上86400秒可能會(huì)有問(wèn)題。
感興趣的可以拿1572764400(太平洋時(shí)間2019-11-03 00:00:00,單位:秒)這個(gè)時(shí)間戳驗(yàn)證下
拿代碼演?下:
PHP:
<?php
echo "PST時(shí)區(qū)的時(shí)間\n";
date_default_timezone_t('PST8PDT');
echo date('Y-m-d H:i:s',1572764400);
echo "\n";
echo date('Y-m-d H:i:s',1572764400+86400);
echo "\n";
//換個(gè)時(shí)區(qū)
echo "換成上海時(shí)區(qū)看看\n";
date_default_timezone_t('Asia/Shanghai');
echo date('Y-m-d H:i:s',1572764400);
echo "\n";
echo date('Y-m-d H:i:s',1572764400+86400);
echo "\n";
運(yùn)?結(jié)果:
PST時(shí)區(qū)的時(shí)間
2019-11-03 00:00:00
2019-11-03 23:00:00
換成上海時(shí)區(qū)看看
2019-11-03 15:00:00
2019-11-04 15:00:00
明明是同?個(gè)時(shí)間戳,都是加上86400(?天),為什么在上海這個(gè)時(shí)區(qū)是第?天,?在PST(美國(guó)太平洋時(shí)區(qū))只加了23?時(shí)?神不神奇!意不意外!
為了弄清楚這個(gè)問(wèn)題,?先得先了解下什么是夏令時(shí),什么是冬令時(shí)
夏令時(shí)
夏令時(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í)。[1]
冬令時(shí)
有夏令時(shí)就會(huì)有冬令時(shí)。?緯度和中緯度的許多國(guó)家在夏季到來(lái)前,把時(shí)針撥快??時(shí),新的時(shí)間就是夏令時(shí),到下半季秋季來(lái)臨前,再把時(shí)針撥回??時(shí),即形成冬令時(shí)。 [2]
夏令時(shí)和冬令時(shí)的影響
拿美國(guó)來(lái)說(shuō),美國(guó)各個(gè)地區(qū)的時(shí)間都不同,不像中國(guó)?樣統(tǒng)?使?北京時(shí)間,美國(guó)?般以三?份第?個(gè)周?凌晨?jī)牲c(diǎn)當(dāng)成夏季的開(kāi)始,???份第?個(gè)周?的凌晨?jī)牲c(diǎn)當(dāng)成冬季的開(kāi)始。
所以在每年的三?份第?個(gè)周?凌晨?jī)牲c(diǎn)過(guò)后,時(shí)間就會(huì)往前調(diào)快?個(gè)?時(shí);同理,???份第?個(gè)周?把這?個(gè)?時(shí)調(diào)回來(lái)。
你也可以理解成美國(guó)那邊,?年??有?天只有23?時(shí)(夏天開(kāi)始那?天),有?天有25?時(shí)(冬天開(kāi)始那?天),其他時(shí)間每天都是24?時(shí)。
所以你會(huì)發(fā)現(xiàn),夏天的時(shí)候,中國(guó)的北京時(shí)間(東?區(qū))與美國(guó)太平洋時(shí)區(qū)(西?區(qū))的時(shí)差是15?時(shí),?到了冬天卻變成16?時(shí)
解決?案
回到開(kāi)頭那個(gè)問(wèn)題,如果我們想直接算第?天,直接加上86400(?天)可能在其他國(guó)家就會(huì)有我上?那個(gè)夏令時(shí)和冬令時(shí)時(shí)間換算的問(wèn)題,要如何避免呢??先能夠確定的是,直接加上86400是不可取的,如果加上?天能否?得通
PHP:
<?php
echo "PST時(shí)區(qū)的時(shí)間\n";
date_default_timezone_t('PST8PDT');
echo date('Y-m-d H:i:s',1572764400);
echo "\n";
echo date('Y-m-d H:i:s',1572764400+86400);
echo "\n";
echo "--------------------------\n";
echo date('Y-m-d H:i:s',1572764400);
echo "\n";
echo date('Y-m-d H:i:s',strtotime('+1 day',1572764400));
echo "\n";
運(yùn)?結(jié)果:
PST時(shí)區(qū)的時(shí)間
2019-11-03 00:00:00
2019-11-03 23:00:00
--------------------------
2019-11-03 00:00:00
2019-11-04 00:00:00
可以看出,不直接加上86400,直接在?期上加上?天是完全沒(méi)問(wèn)題的。
JavaScript:
var date = new Date(1572764400*1000);
date.Date()+1);
var timestamp = Time()/1000);
注意:JS的時(shí)間戳是毫秒
結(jié)論
在經(jīng)濟(jì)全球化快速發(fā)展的今天,在軟件開(kāi)發(fā)的過(guò)程中,盡量養(yǎng)成習(xí)慣,由于夏令時(shí)和冬令時(shí)不是固定的,開(kāi)發(fā)在時(shí)間計(jì)算上應(yīng)該慎?86400進(jìn)?加減運(yùn)算,時(shí)間計(jì)算請(qǐng)直接對(duì)?期進(jìn)?加減,展?時(shí)間給?戶看的時(shí)候盡量結(jié)合當(dāng)?shù)貢r(shí)間,結(jié)合夏令時(shí)和冬令時(shí)計(jì)算出準(zhǔn)確的當(dāng)?shù)貢r(shí)間,避免產(chǎn)?不必要的分歧。
參考:
[1].
[2].