自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你知道程序是怎么處理時(shí)區(qū)問(wèn)題的么?

開(kāi)發(fā) 前端
在實(shí)際業(yè)務(wù)開(kāi)發(fā)中,會(huì)碰到夏令時(shí),閏秒,時(shí)區(qū)轉(zhuǎn)換的問(wèn)題,這些問(wèn)題都需要從業(yè)務(wù)角度去考慮,保證用戶(hù)在任何地區(qū)看到的數(shù)據(jù)都一致的,這就需要MySQL數(shù)據(jù)庫(kù)、后端服務(wù)以及前端服務(wù)做相應(yīng)的處理才能完成。

[[377401]]

本文轉(zhuǎn)載自微信公眾號(hào)「三太子敖丙」,作者三太子敖丙 。轉(zhuǎn)載本文請(qǐng)聯(lián)系三太子敖丙公眾號(hào)。

前言

在實(shí)際業(yè)務(wù)開(kāi)發(fā)中,會(huì)碰到夏令時(shí),閏秒,時(shí)區(qū)轉(zhuǎn)換的問(wèn)題,這些問(wèn)題都需要從業(yè)務(wù)角度去考慮,保證用戶(hù)在任何地區(qū)看到的數(shù)據(jù)都一致的,這就需要MySQL數(shù)據(jù)庫(kù)、后端服務(wù)以及前端服務(wù)做相應(yīng)的處理才能完成。

最近我也剛好在開(kāi)發(fā)的時(shí)候遇到了,所幸就寫(xiě)下這個(gè)比較冷門(mén)的文章,跟大家聊聊夏令時(shí),閏秒,時(shí)區(qū)轉(zhuǎn)換在實(shí)際開(kāi)發(fā)過(guò)程中的解決方案。

夏令時(shí)

夏令時(shí)介紹

夏令時(shí)(Daylight Saving Time:DST):又稱(chēng)"日光節(jié)約時(shí)制",是一種為節(jié)約能源而人為規(guī)定地方時(shí)間的制度,在這一制度實(shí)行期間所采用的統(tǒng)一時(shí)間稱(chēng)為“夏令時(shí)間”。

一般在天亮早的夏季人為將時(shí)間調(diào)快一小時(shí),可以使人早起早睡,減少照明量,以充分利用光照資源,從而節(jié)約照明用電,除了夏令時(shí)外還有冬令時(shí),采用的是本地的標(biāo)準(zhǔn)時(shí)間。

可以看到意大利是有夏令時(shí)制,夏令時(shí)的時(shí)間從3月28日到10月31日,冬令時(shí)(本地標(biāo)準(zhǔn)時(shí)間)是從11月1日到3月27日,在夏令時(shí)時(shí)段內(nèi),時(shí)間比標(biāo)準(zhǔn)時(shí)間快一個(gè)小時(shí),例如羅馬市的時(shí)區(qū)GMT + 1:00,標(biāo)準(zhǔn)時(shí)間為10:00:00,在夏令時(shí)的時(shí)間就是11:00:00,冬令時(shí)的時(shí)間就是10:00:00。

CET (中歐標(biāo)準(zhǔn)時(shí)間) 是UTC + 01:00時(shí)區(qū)的名稱(chēng)之一,比UTC(世界標(biāo)準(zhǔn)時(shí)間)提前1個(gè)小時(shí),與UTC的時(shí)間偏差可寫(xiě)為+01:00,在冬天使用,在夏季時(shí)使用CEST - 中歐夏令時(shí)間 (UTC + 02:00,提前一個(gè)小時(shí))。

LInux時(shí)區(qū)

Linux服務(wù)器的系統(tǒng)時(shí)間的校準(zhǔn)是通過(guò)NTP(Network Time Protocol)服務(wù)來(lái)實(shí)現(xiàn),每隔一段時(shí)間會(huì)跟時(shí)鐘源進(jìn)行校對(duì),確保Linux系統(tǒng)時(shí)間的準(zhǔn)確性,同時(shí)Linux操作系統(tǒng)支持不同國(guó)家及地區(qū)的時(shí)區(qū)設(shè)置,所有時(shí)區(qū)信息位于/usr/share/zoneinfo目錄下,如果需要設(shè)置時(shí)區(qū),只需要將/etc/localtime軟鏈接到一個(gè)具體的地區(qū)即可,如果這個(gè)地區(qū)有DST機(jī)制,那么Linux會(huì)自動(dòng)在DST和標(biāo)準(zhǔn)時(shí)間之間切換,不需要額外的代碼來(lái)處理。

  1. ## Linux支持的區(qū)域信息 
  2. $ ls -ltr /usr/share/zoneinfo/ 
  3. total 320 
  4. lrwxrwxrwx  1 root root     3 10月 23 05:18 Zulu -> UCT 
  5. -rw-r--r--  1 root root  1544 10月 23 05:18 W-SU 
  6. -rw-r--r--  1 root root  1873 10月 23 05:18 WET 
  7. lrwxrwxrwx  1 root root     3 10月 23 05:18 UTC -> UCT 
  8. lrwxrwxrwx  1 root root     3 10月 23 05:18 Universal -> UCT 
  9. -rw-r--r--  1 root root   127 10月 23 05:18 UCT 
  10. -rw-r--r--  1 root root  1970 10月 23 05:18 CET 
  11. ## 前端服務(wù)所在Linux服務(wù)器的時(shí)區(qū) 
  12. $ ls -ltr /etc/localtime  
  13. lrwxrwxrwx 1 root root 33 11月  1 06:20 /etc/localtime -> /usr/share/zoneinfo/Asia/Shanghai 

通過(guò)zdump命令查看下意大利羅馬的時(shí)區(qū)屬性。

  1. $ zdump -v /usr/share/zoneinfo/CET 
  2. /usr/share/zoneinfo/CET  Sun Mar 28 00:59:59 2021 UT = Sun Mar 28 01:59:59 2021 CET isdst=0 gmtoff=3600 
  3. /usr/share/zoneinfo/CET  Sun Mar 28 01:00:00 2021 UT = Sun Mar 28 03:00:00 2021 CEST isdst=1 gmtoff=7200 #2021年夏令時(shí)開(kāi)始 
  4. /usr/share/zoneinfo/CET  Sun Oct 31 00:59:59 2021 UT = Sun Oct 31 02:59:59 2021 CEST isdst=1 gmtoff=7200 #2021年夏令時(shí)結(jié)束 

從上面的信息可以看到,2021年夏令時(shí)的開(kāi)始時(shí)間是Sun Mar 28 01:00:00,結(jié)束時(shí)間為Sun Oct 31 00:59:59,isdst = 1說(shuō)明當(dāng)前處于DST時(shí)段,gmtoff=7200表示與格林治時(shí)間的offset,單位秒,即UTC + 02:00,也稱(chēng)為CEST時(shí)間,這說(shuō)明Linux操作系統(tǒng)已經(jīng)自動(dòng)實(shí)現(xiàn)了下夏令時(shí)DST的自動(dòng)切換。

處理夏令時(shí)

舉個(gè)例子,意大利羅馬的客戶(hù)需要開(kāi)發(fā)一個(gè)稅務(wù)系統(tǒng),用于國(guó)內(nèi)各地市的稅收記賬,由于意大利是有夏令時(shí)制,就需要考慮夏令時(shí)DST的處理,在開(kāi)發(fā)的過(guò)程中,涉及時(shí)間問(wèn)題的包括MySQL數(shù)據(jù)庫(kù)(mysql-server),后端服務(wù)(backend-service)以及前端服務(wù)(frontend-service)三個(gè)方面,下面就從三個(gè)層面分析如何去處理DST。

前端處理

業(yè)務(wù)對(duì)前端的要求是:不管使用的是移動(dòng)端還是PC端,都應(yīng)該正確的顯示當(dāng)時(shí)時(shí)間,包括有夏令時(shí)制的時(shí)間。

如果在中國(guó)的話,就比較好處理,沒(méi)有DST機(jī)制,統(tǒng)一使用東八區(qū)即GMT/UTC + 08:00即可,前端服務(wù)的時(shí)間直接取Linux服務(wù)服務(wù)器的系統(tǒng)時(shí)間,Linux的時(shí)區(qū)只需要設(shè)置為Asia/Shanghai即可,前端不需要做任何時(shí)間的轉(zhuǎn)入轉(zhuǎn)出。

**轉(zhuǎn)入:**指POST請(qǐng)求寫(xiě)入數(shù)據(jù),user —> frontend-service —> backend-service —> mysql-server,例如繳稅接口。

**轉(zhuǎn)出:**指GET請(qǐng)求查詢(xún)數(shù)據(jù),mysql-server —> backend-service —> frontend-service —> user,例如查詢(xún)接口。

不過(guò)開(kāi)心的是,Linux操作系統(tǒng)已經(jīng)自動(dòng)實(shí)現(xiàn)了DST轉(zhuǎn)換,在前端不需要做任何處理,設(shè)置Linux時(shí)區(qū)為CET。

  1. # 修改LInux時(shí)區(qū)為CET,也可以通過(guò)timedatectl命令修改。 
  2. $ ln -sf /usr/share/zoneinfo/CET /etc/localtime 

這樣在意大利國(guó)內(nèi)的用戶(hù)的通過(guò)終端(移動(dòng)端或PC端),登錄系統(tǒng)繳稅或查詢(xún)時(shí),用戶(hù)時(shí)間和前端服務(wù)的時(shí)間完全一致,即完成如下這一步的處理。

后端處理

我們了解了前端Linux服務(wù)器的時(shí)區(qū)設(shè)置為CET,就能自動(dòng)處理意大利DST夏令時(shí)轉(zhuǎn)換了,后端Java程序部署在Linux服務(wù)器上,將其時(shí)區(qū)設(shè)置跟前端一樣,也是CET時(shí)區(qū),后端只需要接收前端傳過(guò)來(lái)的值進(jìn)行MySQL的CRUD操作即可,稅務(wù)表的結(jié)構(gòu)如下:

  1. CREATE TABLE `tax_form` ( 
  2.   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主鍵id'
  3.   `tax_id` varchar(20) NOT NULL DEFAULT '' COMMENT '稅務(wù)編號(hào)'
  4.   `amount` decimal(12,4) NOT NULL DEFAULT '0.0000' COMMENT '納稅金額'
  5.   `tax_payer_id` varchar(20) NOT NULL DEFAULT '' COMMENT '納稅人編號(hào)'
  6.   `status` tinyint NOT NULL DEFAULT '0' COMMENT '繳稅狀態(tài)'
  7.   `audit_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '審核時(shí)間'
  8.   `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間'
  9.   `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時(shí)間'
  10.   PRIMARY KEY (`id`) USING BTREE 
  11. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='稅務(wù)記錄表'

主要看一下繳稅和審核接口,分別的對(duì)應(yīng)的SQL語(yǔ)句如下:

繳稅

  1. -- 繳稅接口的對(duì)應(yīng)的SQL 
  2. insert into tax_form(tax_id,amount,tax_payer_id,status) values('T001', 1234.56, 'U001', 0) 

審核

  1. -- 修改審核狀態(tài) 
  2. update tax_form set status = 1, audit_time = '2021-01-07 12:02:30' where  tax_payer_id = 'U001'

涉及時(shí)間的字段有兩類(lèi)

**公共字段:**create_time,update_time這些是每個(gè)表必須有的時(shí)間字段,而且默認(rèn)都是MySQL的CURRENT_TIMESTAMP,取的MySQL server的當(dāng)前系統(tǒng)時(shí)間,而這個(gè)時(shí)間是跟MySQL的時(shí)區(qū)time_zone設(shè)置不同而變化的,同時(shí)MySQL也是支持夏令時(shí)DST自動(dòng)轉(zhuǎn)換的。

業(yè)務(wù)字段:audit_time審核時(shí)間屬性是由前端頁(yè)面?zhèn)鞯胶蠖诉M(jìn)行處理,后端無(wú)需做任何轉(zhuǎn)換。

MySQL處理

MySQL也是支持夏令時(shí)DST機(jī)制,不過(guò)設(shè)置時(shí)區(qū)time_zone只能設(shè)置為地區(qū)(類(lèi)似Linux設(shè)置時(shí)區(qū)一樣),不能石永紅MySQL設(shè)置的時(shí)區(qū)的相關(guān)變量

  1. mysql> show variables like '%zone%'
  2. +------------------+--------+ 
  3. | Variable_name    | Value  | 
  4. +------------------+--------+ 
  5. | system_time_zone | CST    |   -- 數(shù)據(jù)庫(kù)服務(wù)器的當(dāng)前時(shí)區(qū),不可修改,CST這里指的是中國(guó)標(biāo)準(zhǔn)時(shí)間(China Standard Time UTC+08:00,即東八區(qū)) 
  6. | time_zone        | SYSTEM |   -- 數(shù)據(jù)庫(kù)時(shí)區(qū),默認(rèn)跟服務(wù)器保持一致,可修改。 

目前是東八區(qū),修改為意大利時(shí)區(qū),即東一區(qū)。

  1. mysql> select now(); 
  2. +---------------------+ 
  3. | now()               | 
  4. +---------------------+ 
  5. | 2021-01-07 13:43:31  
  6. -- 修改數(shù)據(jù)庫(kù)時(shí)區(qū)為零時(shí)區(qū),即。 
  7. mysql> set time_zone = 'CET'
  8. ERROR 1298 (HY000): Unknown or incorrect time zone: 'CET' 
  9. -- 嘗試通過(guò)+0:00方式修改,可以成功修改。 
  10. mysql> set time_zone = '+1:00'
  11. Query OK, 0 rows affected (0.00 sec) 

MySQL存儲(chǔ)時(shí)區(qū)信息的數(shù)據(jù)字典

  1. mysql> show tables from mysql like '%time_zone%'
  2. +-------------------------------+ 
  3. | Tables_in_mysql (%time_zone%) | 
  4. +-------------------------------+ 
  5. | time_zone                     |   -- 時(shí)區(qū)信息 
  6. | time_zone_leap_second         |   -- 時(shí)區(qū)閏秒信息 
  7. | time_zone_name                |   -- 時(shí)區(qū)名 
  8. | time_zone_transition          |   -- 時(shí)區(qū)轉(zhuǎn)換 
  9. | time_zone_transition_type     |   -- 時(shí)區(qū)轉(zhuǎn)換類(lèi)型 

默認(rèn)情況下,這些表都是空的,需要通過(guò)MySQL專(zhuān)門(mén)提供的命令mysql_tzinfo_to_sql導(dǎo)入,數(shù)據(jù)會(huì)被插入到表time_zone相關(guān)的表中。

  1. # Linux下的時(shí)區(qū)信息/usr/share/zoneinfo通過(guò)命令mysql_tzinfo_to_sql加載到相關(guān)的time_zone表中。 
  2. $ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql 

執(zhí)行完成之后,看一下表中的數(shù)據(jù),再?lài)L試設(shè)置時(shí)區(qū)為CET。

  1. mysql> select * from mysql.time_zone_name where name like '%CET%'
  2. +------+--------------+ 
  3. Name | Time_zone_id | 
  4. +------+--------------+ 
  5. | CET  |          373 | 
  6. -- 設(shè)置時(shí)區(qū)為CET 
  7. mysql> set time_zone = 'CET'
  8. Query OK, 0 rows affected (0.02 sec) 
  9. mysql> select now(); 
  10. +---------------------+ 
  11. | now()               | 
  12. +---------------------+ 
  13. | 2021-01-07 10:00:36 | 

而且也支持時(shí)區(qū)轉(zhuǎn)換,例如將北京時(shí)間轉(zhuǎn)換成羅馬時(shí)間。

  1. -- 北京時(shí)間17:00:00轉(zhuǎn)換成CET的羅馬時(shí)間就是10:00:00 
  2. mysql> select convert_tz('2021-01-07 17:00:00''Asia/Shanghai''CET'as time
  3. +---------------------+ 
  4. time                | 
  5. +---------------------+ 
  6. | 2021-01-07 10:00:00 | 

我們要解決的問(wèn)題是:MySQL設(shè)置time_zone='CET'后是否能自動(dòng)實(shí)現(xiàn)DST轉(zhuǎn)換,如果可以的話,那么用戶(hù)端、前端服務(wù)、后端服務(wù)以及MySQL服務(wù)器時(shí)區(qū)就統(tǒng)一為CET,同時(shí)都能自動(dòng)處理DST,從上面的zdump -v /usr/share/zoneinfo/CET命令輸出可以看到,2021年意大利的夏令時(shí)從3月28號(hào)01:59:59號(hào)開(kāi)始,也就是時(shí)間調(diào)快一小時(shí)。

  1. -- 01:59:59時(shí)間點(diǎn),沒(méi)有發(fā)生DST切換。 
  2. mysql> select convert_tz('2021-03-28 01:59:59''+1:00''CET'as time
  3. +---------------------+ 
  4. time                | 
  5. +---------------------+ 
  6. | 2021-03-28 01:59:59 |  
  7. -- 02:00:00時(shí)間點(diǎn),確實(shí)發(fā)生DST切換,從02:00:00調(diào)快了一小時(shí)變成了03:00:00 
  8. mysql> select convert_tz('2021-03-28 02:00:00''+1:00''CET'as time
  9. +---------------------+ 
  10. time                | 
  11. +---------------------+ 
  12. | 2021-03-28 03:00:00 | 
  13. -- 將+1:00時(shí)間換成CET,結(jié)果也是一樣的,發(fā)生了DST切換。 
  14. mysql> select convert_tz('2021-03-28 02:00:00''CET''CET'as time
  15. +---------------------+ 
  16. time                | 
  17. +---------------------+ 
  18. | 2021-03-28 03:00:00 | 

從上面的結(jié)果可以看到,當(dāng)time_zone設(shè)置成地區(qū)/城市,系統(tǒng)會(huì)自動(dòng)解決夏令時(shí)DSTQ切換問(wèn)題,如果設(shè)置time_zone='+1:00’這種方式就失去了夏令時(shí)機(jī)制,目前在MySQL數(shù)據(jù)庫(kù)中,在初始化time_zone相關(guān)表元數(shù)據(jù)以后,MySQL就可以自己完成夏令時(shí)的修正,不需要額外的服務(wù)處理。

對(duì)于AWS RDS的來(lái)說(shuō),time_zone是可以選擇地區(qū)/城市的,也就是支持夏令時(shí)的自動(dòng)切換。

處理夏令時(shí)總結(jié)

通過(guò)上面的分析可以知道,Linux服務(wù)器和MySQL服務(wù)器都可以自動(dòng)處理DST切換,前提是需要設(shè)置Linux的時(shí)區(qū)和MySQL時(shí)區(qū)為地區(qū),例如都設(shè)置為CET。

閏秒

指為保持協(xié)調(diào)世界時(shí)接近于世界時(shí)時(shí)刻,由國(guó)際計(jì)量局統(tǒng)一規(guī)定在年底或年中(也可能在季末)對(duì)協(xié)調(diào)世界時(shí)增加或減少1秒的調(diào)整。最近一次閏秒在北京時(shí)間2017年1月1日7時(shí)59分59秒(時(shí)鐘顯示07:59:60)出現(xiàn)。

在實(shí)際的業(yè)務(wù)系統(tǒng),受閏秒影響的有Linux服務(wù)器,Java代碼以及MySQL數(shù)據(jù)庫(kù),我們來(lái)看看它們分別是怎么解決的LeapSecond問(wèn)題的。

Linux服務(wù)器

對(duì)于大多數(shù)新的linux內(nèi)核(2.6.x內(nèi)核以后是支持LeapSecond,在這之前可能會(huì)導(dǎo)致Linux Kernel Crash),在設(shè)計(jì)時(shí)都是支持閏秒的,Linux操作系統(tǒng)時(shí)間是通過(guò)NTP服務(wù)來(lái)和時(shí)鐘源來(lái)進(jìn)行同步,NTP會(huì)一級(jí)一級(jí)地下發(fā)閏秒事件通知直到最邊緣的NTP服務(wù)器,然后NTP就會(huì)把閏秒通知給客戶(hù)端的操作系統(tǒng),由操作系統(tǒng)來(lái)處理閏秒通知。

對(duì)于閏秒2017-01-01 07:59:60,Linux內(nèi)核需要處理這個(gè)時(shí)間,就需要做一些特定的處理,一般會(huì)有以下三種方案。

  • 后退一秒
  • 停止一秒
  • 真正的增加一秒

第一種方式會(huì)導(dǎo)致一些基于timestamp的消息通知亂序了,而第二種會(huì)導(dǎo)致出現(xiàn)兩個(gè)一模一樣的timestamp,而最后一種不會(huì)出現(xiàn)timestamp的問(wèn)題,也是后面Linux內(nèi)核選擇的處理方案。

  1. mysql> select UNIX_TIMESTAMP('2017-01-01 07:59:59'as nts; 
  2. +------------+ 
  3. | nts        | 
  4. +------------+ 
  5. | 1483257599 | 
  6. date -d '@1483257599' --utc 
  7. Sun Jan  1 07:59:59 UTC 2017 
  8. date -d '@1483257600' --utc 
  9. Sun Jan  1 08:00:00 UTC 2017 

從這里可以看到,Linux采用的是第三種方案:真正的增加一秒,這也符合業(yè)務(wù)系統(tǒng)的需求。

Java代碼

Java代碼的System.currentTimeMillis()會(huì)產(chǎn)生閏秒60,是取決于Linux操作系統(tǒng)的,在Linux Kernel 2.6.x之后已經(jīng)fix了LeapSecond問(wèn)題。

MySQL數(shù)據(jù)庫(kù)

上面看到了在MySQL下已經(jīng)有了mysql.time_zone_leap_second數(shù)據(jù)字典,說(shuō)明已經(jīng)支持了LeapSecond,處理方案跟Linux類(lèi)似。

  1. -- 創(chuàng)建一張測(cè)試表存儲(chǔ)timestamp時(shí)間戳 
  2. CREATE TABLE ls(   
  3. id bigint NOT NULL COMMENT 'id'
  4. ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  5. PRIMARY KEY (id)); 
  6. -- 設(shè)置數(shù)據(jù)庫(kù)時(shí)區(qū)為UTC 
  7. mysql> set time_zone = 'UTC'
  8. mysql> set timestamp = 1483257599;  --對(duì)應(yīng)時(shí)間:2017-01-01 07:59:59 
  9. mysql> insert into ls(id) values(1); 
  10. mysql> set timestamp = 1483257600;  --對(duì)應(yīng)時(shí)間:2017-01-01 07:59:60 
  11. mysql> insert into ls(id) values(2); 
  12. -- 可以看到MySQL對(duì)閏秒進(jìn)行了處理,將07:59:60轉(zhuǎn)換成了08:00:00。 
  13. mysql> select id, ts, unix_timestamp(ts) from ls; 
  14. +----+---------------------+--------------------+ 
  15. | id | ts                  | unix_timestamp(ts) | 
  16. +----+---------------------+--------------------+ 
  17. |  1 | 2017-01-01 07:59:59 |         1483257599 | 
  18. |  2 | 2017-01-01 08:00:00 |         1483257600 | 
  19. -- 通過(guò)閏秒時(shí)間查詢(xún)會(huì)報(bào)錯(cuò) 
  20. mysql> select * from ls where ts = '2017-01-01 07:59:60'
  21. ERROR 1525 (HY000): Incorrect TIMESTAMP value: '2017-01-01 07:59:60' 
  22. mysql> select * from ls where ts = '2017-01-01 08:00:00'
  23. +----+---------------------+ 
  24. | id | ts                  | 
  25. +----+---------------------+ 
  26. |  2 | 2017-01-01 08:00:00 | 

跨境系統(tǒng)的時(shí)間處理

上面介紹的意大利羅馬的稅務(wù)系統(tǒng),其實(shí)屬于政企業(yè)務(wù),只服務(wù)于國(guó)內(nèi)的用戶(hù)的需求,不涉及海外用戶(hù)的請(qǐng)求,相對(duì)來(lái)說(shuō)地區(qū)和人員都比較固定,但是像這種跨境電商巨頭ebay,它服務(wù)的用戶(hù)遍布全球各地,而且每個(gè)地區(qū)的時(shí)區(qū)不同,同時(shí)每個(gè)時(shí)區(qū)的夏令時(shí)DST的起始時(shí)間也不一樣,我們要解決的是要根據(jù)客戶(hù)所在地區(qū)顯示正確的時(shí)間(包括DST),跟前面的DST處理一樣也涉及到三端處理:前端服務(wù)(frontend-service),后端服務(wù)(backend-service)以及MySQL數(shù)據(jù)庫(kù)(mysql-server)。

從這個(gè)圖上可以看到,前端服務(wù)的UI層跟用戶(hù)所在的地區(qū)時(shí)間要完全一致,至于后端服務(wù)和MySQL如何處理時(shí)間,對(duì)于用戶(hù)來(lái)說(shuō)根本不關(guān)心的,這就要求前端必須要根據(jù)不同地區(qū),不同時(shí)區(qū),不同夏令時(shí)DST產(chǎn)生不同的時(shí)間的用戶(hù)進(jìn)行轉(zhuǎn)換處理,不同地區(qū)的時(shí)間轉(zhuǎn)換目前前端(Vue/React)已經(jīng)有現(xiàn)成的插件可直接使用。

同時(shí)希望只在前端處理用戶(hù)時(shí)間的轉(zhuǎn)入和轉(zhuǎn)出,后端和MySQL數(shù)據(jù)庫(kù)不做任何修改就能完成業(yè)務(wù)處理和數(shù)據(jù)存儲(chǔ)。

北京用戶(hù)在UTC + 8也就是東八區(qū),而羅馬用戶(hù)在UTC + 1東一區(qū),都是在UTC的基礎(chǔ)上做處理,那我們就可以將時(shí)區(qū)都設(shè)置為UTC,然后根據(jù)用戶(hù)所在地區(qū)進(jìn)行相應(yīng)的處理。

MySQL處理

設(shè)置MySQL數(shù)據(jù)庫(kù)的時(shí)區(qū)為UTC,不管用戶(hù)來(lái)自哪個(gè)地區(qū)存儲(chǔ)在數(shù)據(jù)庫(kù)的時(shí)間都是UTC,包括公共時(shí)間字段(創(chuàng)建時(shí)間,修改時(shí)間)以及業(yè)務(wù)時(shí)間字段(交易開(kāi)始時(shí)間,交易結(jié)束時(shí)間)。

-- 設(shè)置數(shù)據(jù)庫(kù)時(shí)區(qū)為UTC,即零時(shí)區(qū)

  1. -- 設(shè)置數(shù)據(jù)庫(kù)時(shí)區(qū)為UTC,即零時(shí)區(qū) 
  2. set global time_zone = 'UTC' 

后端處理

MySQL時(shí)區(qū)是UTC,那么后端服務(wù)的所在的Linux Server時(shí)區(qū)統(tǒng)一設(shè)置為UTC,跟MySQL保持一致,這樣后端就不需要做任何轉(zhuǎn)換。

前端處理

前端拿到標(biāo)準(zhǔn)時(shí)區(qū)UTC的數(shù)據(jù),統(tǒng)一根據(jù)用戶(hù)所在時(shí)區(qū)進(jìn)行轉(zhuǎn)換,這樣保證與后端數(shù)據(jù)時(shí)區(qū)的一致性,前端根據(jù)實(shí)際情況進(jìn)行渲染。一般來(lái)講,前端將時(shí)間數(shù)據(jù)傳遞到后端,后端封裝成timestamp后存儲(chǔ)在MySQL中對(duì)應(yīng)timestamp類(lèi)型(MySQL中的timestamp是不區(qū)分時(shí)區(qū)的,例如數(shù)據(jù)庫(kù)是UTC 02:00:00,北京用戶(hù)使用ebay在CST 10:00:00下單,數(shù)據(jù)庫(kù)中的訂單表的create_time就應(yīng)該存儲(chǔ)2020-12-03 10:00:00),同時(shí)前端查詢(xún)數(shù)據(jù)的也要做相應(yīng)的轉(zhuǎn)換處理。

定時(shí)任務(wù)

后端服務(wù)一般都會(huì)一些定時(shí)任務(wù),這個(gè)時(shí)間一般取自Linux OS的時(shí)間,跟前端沒(méi)關(guān)系,基于Linux的UTC時(shí)區(qū)做相應(yīng)的調(diào)整即可。

總結(jié)

上面介紹了夏令時(shí),閏秒以及跨境系統(tǒng)的時(shí)間處理問(wèn)題,主要涉及到MySQL數(shù)據(jù)庫(kù),后端服務(wù)以及前端服務(wù)三個(gè)層面,對(duì)于夏令時(shí),閏秒的轉(zhuǎn)換處理,Linux和MySQL都可以自動(dòng)完成處理,不需要額外轉(zhuǎn)換;對(duì)于跨境系統(tǒng)的時(shí)間處理,通過(guò)設(shè)置Linux和MySQL時(shí)區(qū)為UTC,只需要前端服務(wù)處理不同地區(qū)用戶(hù)時(shí)間問(wèn)題,降低了系統(tǒng)改造的風(fēng)險(xiǎn),今天就聊這么多,希望對(duì)大家有所幫助。

 

責(zé)任編輯:武曉燕 來(lái)源: 三太子敖丙
相關(guān)推薦

2023-04-28 07:44:44

MyBatis查詢(xún)SQL

2023-08-30 07:27:39

2022-02-10 09:04:50

架構(gòu)

2024-04-08 00:00:00

asyncawaiPromise

2019-09-20 08:47:57

DockerLinux軟件

2024-12-04 08:40:19

2013-02-27 10:27:44

GitHub

2017-12-11 15:04:58

404錯(cuò)誤HTTP代碼

2015-03-24 14:02:45

程序員

2024-02-19 00:00:00

Docker輕量級(jí)容器

2024-04-10 10:15:16

監(jiān)聽(tīng)

2020-06-29 18:54:39

大數(shù)據(jù)新發(fā)地疫情

2024-11-26 00:45:29

free區(qū)域字段

2010-01-06 15:36:30

Linux操作系統(tǒng)

2023-10-08 09:42:41

GitHubDataTable?Fill

2020-12-17 08:56:51

單例模式JVM

2020-12-08 09:25:41

死鎖MySQL數(shù)據(jù)庫(kù)

2024-12-11 08:19:34

2022-08-11 17:14:37

Java

2022-12-09 09:46:55

插件Lombok
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)