同一個(gè)頁(yè)面的時(shí)間變來(lái)變?nèi)ィ姽砹?/h1>
低并發(fā)編程
戰(zhàn)略上藐視技術(shù),戰(zhàn)術(shù)上重視技術(shù)
事情的起因是這樣的,上篇文章我發(fā)了 Spring 的一個(gè)官方技術(shù)大會(huì) SpringOne 的預(yù)告。 隨便逛了下發(fā)現(xiàn)了 SpringOne 就在今晚
其中里面的大會(huì)時(shí)間表在官網(wǎng)是這樣的。 
大家注意看大會(huì)第一項(xiàng)的時(shí)間欄里,寫的是: 9:00 PM - 10:00 PM CST 也就是當(dāng)天晚上的九點(diǎn)正式開始(八點(diǎn)開始有影像)。 但有個(gè)讀者這樣一條評(píng)論引發(fā)了我的思考。 
我查了下 CST 這個(gè)時(shí)區(qū)縮寫,分別可以表示以下這么多時(shí)區(qū)的縮寫: 美國(guó)中部時(shí)間:Central Standard Time (USA) UTC-6:00 澳大利亞中部時(shí)間:Central Standard Time (Australia) UTC+9:30 中國(guó)標(biāo)準(zhǔn)時(shí)間:China Standard Time UTC+8:00 古巴標(biāo)準(zhǔn)時(shí)間:Cuba Standard Time UTC-4:00 我是通過分析得出,如果是美國(guó)時(shí)間的晚上 8 點(diǎn)開始,那整個(gè)會(huì)就大部分都是凌晨多進(jìn)行的,感覺不大合理,所以推測(cè)這應(yīng)該是中國(guó)的時(shí)間,也就是 China Standard Time UT+8:00。 但細(xì)想想又覺得不大對(duì)勁,這 Spring 官網(wǎng)還照顧到我是中國(guó)人,然后專門為我顯示中國(guó)時(shí)間?而且它是咋知道我是中國(guó)人的呢? 我讓我一個(gè)美國(guó)的朋友訪問了下這個(gè)頁(yè)面,果然時(shí)間和我顯示的不一樣: 
是 6:00 AM - 7:00 AM PDT PDT 代表太平洋夏令時(shí) Pacific Daylight Time UTC-7:00 我又讓我一個(gè)英國(guó)的朋友訪問了下,得到: 2:00 PM - 3:00 PM BST BST 代表英國(guó)夏令時(shí)間 British Summer Time UTC+1:00 我又讓我一個(gè)德國(guó)的朋友訪問了下,得到: 3:00 PM - 4:00 PM CEST CEST 代表歐洲中部夏令時(shí)間 Central Europen Summer Time UTC+2:00 我國(guó)外就這么些朋友了,這事就得到了驗(yàn)證,SpringOne 官網(wǎng)上我看到的 CST 肯定就代表中國(guó)時(shí)間了,因?yàn)檫@個(gè)網(wǎng)站顯示的時(shí)間會(huì)隨著訪問人的時(shí)區(qū)而變化。
啥原理
然后我又想,這原理應(yīng)該是請(qǐng)求頭加了什么參數(shù),標(biāo)識(shí)了我的時(shí)區(qū)? 可是我抓包后,沒發(fā)現(xiàn)有類似的參數(shù)。 然后我又想,那應(yīng)該是根據(jù)我的請(qǐng)求 IP 判斷的? 于是我 [那啥] 了一下,發(fā)現(xiàn)無(wú)論怎么切換 vpn,顯示的時(shí)間一直是 CST,中國(guó)時(shí)間。 正當(dāng)一籌莫展的時(shí)候,我又問了我一個(gè)快回國(guó)的英國(guó)朋友,他訪問之后居然顯示的也是中國(guó)時(shí)間! 9:00 PM - 10:00 PM CST 然后他說了一句話,一句點(diǎn)醒夢(mèng)中人,他說他馬上就要回國(guó)了,為了提前適應(yīng),所以把電腦的時(shí)區(qū)設(shè)置成了中國(guó)。 
原來(lái)如此! 我馬上把我的時(shí)區(qū)調(diào)整成了美國(guó)的太平洋時(shí)間。 
重新打開瀏覽器,訪問 SpringOne。 
時(shí)間終于變成了美國(guó)太平洋時(shí)間,證明了美國(guó)人是早上開始看這個(gè)大會(huì),然后持續(xù)一整天。我們中國(guó)人是晚上開始看,然后如果要追直播則需要通宵了。 同時(shí)也證明了,頁(yè)面上顯示的時(shí)間,和我操作系統(tǒng)系統(tǒng)設(shè)置的時(shí)區(qū)有關(guān)。
刨根問底繼續(xù)探索
話說回來(lái),這個(gè)網(wǎng)站的 H5 頁(yè)面,是怎么和我系統(tǒng)的時(shí)間打交道的呢?
我開始抓包。 首先這個(gè)肯定不是個(gè)靜態(tài)頁(yè)面了,因此一定是個(gè) js 動(dòng)作。 在茫茫一片 js 包中我找到了一個(gè)叫 schedule.js 的,一看就是負(fù)責(zé)給這些時(shí)間賦值的。 
注意到這里面在獲取時(shí)間時(shí),大量用了 getUnixTimestamp 方法。 于是我又在另一個(gè) js 里面找到了這個(gè)方法的定義,在 core.min.js 里。 
這個(gè)方法被壓縮了,把它格式化一下,再拎出關(guān)鍵信息,如下: $tzDatetimes:$(".tz-datetime")
a.$tzDatetimes.each(function() {
d.convertDatetime(this)
})
convertDatetime:function(b) {
var c=b.dataset.datetimeOut
}
var h = moment.tz.guess()
var c = b.dataset.datetimeOut
getUnixTimestamp:function(b,c){
return moment
.tz(b,c||"MM/DD/YYYY HH:mm", "America/New_York")
.tz(h)
.valueOf()
}
重點(diǎn)看這個(gè)函數(shù) var h = moment.tz.guess()
這個(gè)函數(shù)就是和系統(tǒng)設(shè)置時(shí)區(qū)交互的關(guān)鍵,它可以查看你的所在時(shí)區(qū),準(zhǔn)確說是你系統(tǒng)設(shè)置的時(shí)區(qū)。
我把系統(tǒng)時(shí)區(qū)設(shè)置成美國(guó)太平洋時(shí)區(qū)(UTC-8:00),瀏覽器 console 里執(zhí)行這個(gè) js 代碼后,得到如下結(jié)果: >> moment.tz.guess();
"America/Los_Angeles"
我又把系統(tǒng)時(shí)區(qū)設(shè)置成中國(guó)北京時(shí)間(UTC+8:00),瀏覽器 console 里執(zhí)行這個(gè) js 代碼后,得到如下結(jié)果: >> moment.tz.guess();
"Asia/Shanghai"
這一切就通了,這個(gè) js 函數(shù)可以獲取到我們系統(tǒng)設(shè)置的時(shí)區(qū),也就自然可以隨著系統(tǒng)時(shí)區(qū),來(lái)動(dòng)態(tài)變化頁(yè)面上的時(shí)間了。 具體怎么變化,就是通過剛剛的 getUnixTimestamp 這個(gè)函數(shù)了。 getUnixTimestamp:function(b,c){
return moment
.tz(b,c||"MM/DD/YYYY HH:mm", "America/New_York")
.tz(h)
.valueOf()
}
我們知道 h 就代表時(shí)區(qū),那么這第一行 tz 就是用美國(guó)紐約時(shí)間來(lái)設(shè)定一個(gè)初始值,第二行 tz 轉(zhuǎn)化為我們系統(tǒng)設(shè)置的時(shí)區(qū),第三行 valueOf 最終可以轉(zhuǎn)化成一個(gè)時(shí)間戳。 我們隨便拿一個(gè)值瀏覽器 console 里執(zhí)行這個(gè)函數(shù)驗(yàn)證一下,比如我們想看看美國(guó)紐約時(shí)間的 2021-09-01 08:00 轉(zhuǎn)換成北京時(shí)間(我系統(tǒng)設(shè)置的時(shí)間)的結(jié)果是什么。 >> moment \
>> .tz("09/01/2021 08:00","MM/DD/YYYY HH:mm", "America/New_York") \
>> .tz(moment.tz.guess()) \
>> .valueOf()
1630497600000
這個(gè) 1630497600000 用時(shí)間戳轉(zhuǎn)換工具轉(zhuǎn)換下,就是: 
完美,這個(gè)函數(shù)把美國(guó)紐約時(shí)間的 2021-09-01 08:00 轉(zhuǎn)換成了北京時(shí)間的 2021-09-01 20:00,剛好差 12 個(gè)小時(shí)嘛,沒毛病。 于是乎這個(gè)轉(zhuǎn)換后的值,就填充到頁(yè)面上 class 為 tz-datetime 這個(gè)標(biāo)簽下了。 $tzDatetimes:$(".tz-datetime")
a.$tzDatetimes.each(function() {
d.convertDatetime(this)
})
沒錯(cuò),就是我們看到的位置。 
至此,本問題終于完美解釋了! 感謝這位讀者提出的問題,感謝各國(guó)親朋好友提供的支持,讓我有了一個(gè)快樂探索的下午,以及這篇隨性而發(fā)的文章! 做技術(shù)人我覺得這點(diǎn)比較好,就是毫無(wú)目的,只為解答一個(gè)心中的疑惑,就愿意花上一下午時(shí)間去研究研究,同時(shí)得出結(jié)論后的那種快樂,我覺得是獨(dú)有的一種享受。 那我的話還有雙倍快樂,就是寫成文章給大家看,看大家的留言、點(diǎn)贊。 希望對(duì)大家有幫助~
瀏覽
76
低并發(fā)編程


啥原理



刨根問底繼續(xù)探索


$tzDatetimes:$(".tz-datetime")
a.$tzDatetimes.each(function() {
d.convertDatetime(this)
})
convertDatetime:function(b) {
var c=b.dataset.datetimeOut
}
var h = moment.tz.guess()
var c = b.dataset.datetimeOut
getUnixTimestamp:function(b,c){
return moment
.tz(b,c||"MM/DD/YYYY HH:mm", "America/New_York")
.tz(h)
.valueOf()
}
var h = moment.tz.guess()>> moment.tz.guess();
"America/Los_Angeles"
>> moment.tz.guess();
"Asia/Shanghai"
getUnixTimestamp:function(b,c){
return moment
.tz(b,c||"MM/DD/YYYY HH:mm", "America/New_York")
.tz(h)
.valueOf()
}
>> moment \
>> .tz("09/01/2021 08:00","MM/DD/YYYY HH:mm", "America/New_York") \
>> .tz(moment.tz.guess()) \
>> .valueOf()
1630497600000

$tzDatetimes:$(".tz-datetime")
a.$tzDatetimes.each(function() {
d.convertDatetime(this)
})

評(píng)論
圖片
表情
