一、說(shuō)在前面
首先明白,應(yīng)用里有兩個(gè)地方可設(shè)置時(shí)區(qū),
一是application里的timezone,
這里的時(shí)區(qū)設(shè)置是整個(gè)應(yīng)用的時(shí)區(qū)設(shè)置,在Application.php源碼里可看到:它會(huì)作用于date函數(shù),

這里有這樣的一個(gè)場(chǎng)景:
A是UTC時(shí)區(qū)的用戶,他電腦上顯示的時(shí)間是上午12點(diǎn),他在Yii2(應(yīng)用時(shí)區(qū)設(shè)置是PRC)上創(chuàng)建的一條數(shù)據(jù),那這條記錄的created_at是什么時(shí)間?是的,created_at是PRC的時(shí)間,即晚上8點(diǎn)。因?yàn)閏reated_at是通過(guò)date函數(shù)生成。
二是formatter的defaultTimeZone和timeZone 屬性
使用formatter轉(zhuǎn)換時(shí)間時(shí),會(huì)先判斷這里的defaultTimeZone與formatter中的timezone的時(shí)間差,然后將轉(zhuǎn)換后的時(shí)間顯示出來(lái)。
時(shí)區(qū)轉(zhuǎn)換參考代碼:yii::$app->formatter->asDatetime($model['updated_at'],'full');
時(shí)區(qū)轉(zhuǎn)換:從defaultTimeZone時(shí)區(qū)轉(zhuǎn)到timezone時(shí)區(qū),因此,defaultTimeZone的值需與application中的timezone保持一致
(若formatter的timezone未指定,默認(rèn)取application的timezone,需要轉(zhuǎn)換時(shí)區(qū)顯示的時(shí)候,修改formatter的timezone即可)
這里是一個(gè)簡(jiǎn)單的例子:
formatter里的timezone是UTC
formatter的defaultTimeZone是PRC
數(shù)據(jù)庫(kù)有一條記錄時(shí)間值是
2019-04-04? 20:00:00
那在頁(yè)面上使用formatter轉(zhuǎn)換時(shí)間時(shí),顯示的時(shí)間是多少?
2019-04-04? 12:00:00
二、既然是國(guó)際化應(yīng)用,難免會(huì)有不同時(shí)區(qū)的用戶在使用同一個(gè)yii2應(yīng)用,這個(gè)時(shí)候,時(shí)間如何處理?
1、應(yīng)用時(shí)區(qū)設(shè)置:
application里的timezone是PRC
formatter里的timezone是PRC(目標(biāo)時(shí)區(qū))
formatter的defaultTimeZone是PRC
場(chǎng)景:UTC用戶和PRC用戶同時(shí)在Yii2上寫工作日志,能夠查看對(duì)方的記錄
數(shù)據(jù)庫(kù)有記錄時(shí)間兩個(gè)的字段:created_at和work_date
created_at是應(yīng)用通過(guò)date函數(shù)生成,work_date是用戶通過(guò)HTML界面日期組件選擇的,
因?yàn)椴煌瑫r(shí)區(qū)的用戶,終端電腦的時(shí)間是不一樣的,
假如UTC用戶選擇work_date為當(dāng)前時(shí)間:上午12點(diǎn),但實(shí)際上created_at字段入庫(kù)的時(shí)間是晚上8點(diǎn)(PRC)。那UTC的用戶就很尷尬了,明明現(xiàn)在只是中午12點(diǎn),看到這條記錄的創(chuàng)建時(shí)間卻是20點(diǎn),時(shí)間穿越了?
這里是解決的方案:
1、用戶必須選擇自己所在的時(shí)區(qū),
2、通過(guò)組件選擇的時(shí)間字段需全部轉(zhuǎn)換成PRC時(shí)間入庫(kù),也就是work_date入庫(kù)時(shí)間應(yīng)該為20點(diǎn)
3、保存后查看時(shí),將work_date和created_at通過(guò)formatter(defaultTimeZone是PRC,timezone是UTC)轉(zhuǎn)后顯示出來(lái)
? 都將顯示為上午12點(diǎn)。
總而言之:
1、formatter的defaultTimeZone必須與application的timezone保持一致,
2、只能通過(guò)修改formatter里的timezone來(lái)修改顯示的時(shí)區(qū)時(shí)間,
3、所有時(shí)間字段在入庫(kù)時(shí),必須保持與application->timezone的時(shí)區(qū)時(shí)間一致,
4、項(xiàng)目一旦部署,不要再修改application->timezone,更不能由用戶選擇時(shí)區(qū)而改變application->timezone。
5、application->timezone可以在common\config\main.php中設(shè)置,也可以在每個(gè)應(yīng)用中的config\main.php中設(shè)置