Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Q18. [個人技能題組][Backend] 基礎: 時區 #25

Open
Leeboyd opened this issue Apr 6, 2017 · 5 comments
Open

Q18. [個人技能題組][Backend] 基礎: 時區 #25

Leeboyd opened this issue Apr 6, 2017 · 5 comments

Comments

@Leeboyd
Copy link

Leeboyd commented Apr 6, 2017

時間格式是新手入坑肯定會摔跤的地方,試著回答下列問題。

  1. UTC 是什麼?能表示時區嗎?
  2. Timestamp 是什麼?能表示時區嗎?
  3. DB 能不能設定時區 (以 mysql 為例)
  4. 程式能不能設定時區 (以 nodejs 為例)
  5. 系統能不能設定時區 (以 linux 為例)
  6. DB 內的日期時間欄位若存 string 和存 timestamp 和存 datetime 有什麼差別
  7. Mysql 欄位格式 timestamp 和 datetime 的差別是什麼
  8. 請問分別在伺服器上用 UTC 跟用本地時區的好處跟壞處在哪?
  9. 系統(伺服器)的時區設定是否會影響 DB 中的資料?
  10. (限mysql/mariadb)今天在 DB 中新增一個欄位,當時欄位型別是寫 boolean,但實際上開起來根本不是 boolean。這中間發生了什麼事情?
  11. 承上,實際上開的型別跟 boolean 是什麼關係?

@tnstiger 建議這麼做:
不弄懂這些問題,那你就會像隻跑回圈的老鼠,永遠都搞不清楚要怎麼用

  • 在一個 table 放一個 timestamp 的欄位
  • 然後 INSERT INTO test VALUES (‘2017-04-05 18:19:03')
  • 看看他的 value 是什麼

答題時間: ? hr

@dustfantasy
Copy link

dustfantasy commented Apr 6, 2017

「於2017/04/06 開始答題」
1.UTC國際協調時間
最主要的世界時間標準,UTC+0為0度經線的時間,以其為基準正負十二表示時區。
像是UTC+8比UTC+0的時間快八個小時。

2.timestamp是從某個時間(格林威治时间1970年01月01日00时00分00秒)起到現在的總秒數,每個地方的數值都一樣,因此無法表示時區。
舉例:UST+8相差八小時,UTC+0 00:00 這個時間在UTC+8為08:00,經過一分鐘,UTC+0 00:01,UTC+8 08:01,兩者的timestamp都為60。

3.可以
得知時間
select now();
得知時區設置
SELECT @@system_time_zone, @@global.time_zone, @@session.time_zone;
設定時區
mysql> SET time_zone = timezone;
SET GLOBAL time_zone = timezone;
更改time_zone可以立即觀察到更改時區後的時間, GLOBAL time_zone 則為下次登入後預設的時區
這兩個都是以UTC為基準,更改範例SET time_zone = '+8:00'; 此為UTC+8。

關於這個
set system_time_zone = CST;
會提示出'system_time_zone' is a read only variable的錯誤,似乎是不能更動的。

另外資料庫的預設時區是跟系統時區相關的,若是更改系統時區資料庫的時區也會跟著變更,也就是system_time_zone會跟著改變。

4.不能
node中以Date()取得系統時間,雖然可以更改顯示出的時間,但實際上不能對系統時區做更動,而資料庫因為可以使用語法變動時區,因此能在node使用sql的話應該也是可以更動資料庫時區的。

5.可以
使用sudo dpkg-reconfigure tzdata修改時區後重新開機,時區就會變更,此時資料庫時區沒特別預設也會改變。

6.時間欄位型態的差別
string
可以自定義時間格式,但對於時間字串的處理必須自己寫
datetime跟timestamp有既定格式與限制。
datetime跟timestamp能表示的範圍限制不同。
datetime的值為固定值,timestamp值會因時區設置改變而改變
(假設現在有值都為12:00:00,接著去變更時區datetime值為12:00:00 而timestamp則會因時區改變)

7.timestamp 和 datetime 的差別
timestamp
a.4 bytes(相對於datetime更輕量,索引更快)
b.以UTC格式保存
c.時區轉化
d.年不能早於1970或晚於2037
e.預設not null,給null值會給予當前時間作為值
f.值會因時區設置改變而改變

datetime
a.8 bytes
b.實際格式儲存
c.與時區無關
d.1000-01-01 00:00:00'到9999-12-31 23:59:59
e.可以為null
f.值固定不變,不受時區影響

8.使用UTC由於是世界通用,若有不同時區使用者則能統一時間資訊,但若只有在同一時區上,由於時間上會相差八小時造成不易辨別。
使用本地時區則相反,在本地使用上容易辨識,但對於其他時區的使用者卻有時區差異的問題存在。

9.由於一般資料庫時區域設為系統時區,所以一旦系統時區變更資料庫也跟著改變。

10.因為mysql/mariadb資料庫中沒有boolean型態,因此預設會將bool型態轉為tinyint(1)。

11.效用都一樣,tinyint(1)表示1bit的int,因為boolean只有兩種值——true和false,在邏輯運算中同時也代表1跟0,因此使用1bit的int便可以用來當作boolean值使用。

「於2017/04/08 答題結束」

@PenguinRun
Copy link

PenguinRun commented Apr 6, 2017

「於2017/04/06 開始答題」
https://medium.com/@justinlee_78563/%E9%97%9C%E6%96%BC%E6%99%82%E5%8D%80-4bfada7bd23d

「於2017/04/07 答題結束」

@HoHow
Copy link

HoHow commented May 1, 2017

「於2017/05/01 開始答題」

UTC 是什麼?能表示時區嗎?
最主要的世界時間標準,其以原子時秒長為基礎,在時刻上儘量接近於格林威治標準時間。
可以表示時區

Timestamp 是什麼?能表示時區嗎?
這個起始日期與時間使用UTC世界標準時間為儲存資料的依據,它與「Greenwich Mean Time、GMT」格林威治標準時間是一樣的。
可以表示時區

DB 能不能設定時區 (以 mysql 為例)
可以
SET TIME_ZONE = ‘+8:00’; 設定+8時區

程式能不能設定時區 (以 nodejs 為例)
不可以
會以系統時區為準

系統能不能設定時區 (以 linux 為例)
可以
DB 內的日期時間欄位若存 string 和存 timestamp 和存 datetime 有什麼差別

Mysql 欄位格式 timestamp 和 datetime 的差別是什麼
timestamp可以用時區判斷地區
timestamp只能顯示大於1970或小於2038
datetime 不能用時區判斷
datetime可以顯示到9999-12-31 23:59:59
請問分別在伺服器上用 UTC 跟用本地時區的好處跟壞處在哪?
如果是使用者都是本地可以用本地時區就好
使用者是全國的話用UTC比較好,可以判斷時區,回傳正確的時間給使用者

系統(伺服器)的時區設定是否會影響 DB 中的資料?

DB的時間是以系統時間為準

(限mysql/mariadb)今天在 DB 中新增一個欄位,當時欄位型別是寫 boolean,但實際上開起來根本不是 boolean。這中間發生了什麼事情?
在mysql tinyint = boolean 他們是一樣的 true = 1 false =0
承上,實際上開的型別跟 boolean 是什麼關係?
boolean在mysql中使用的欄位是tinyint(1),他跟boolean做相同的事

在一個 table 放一個 timestamp 的欄位
然後 INSERT INTO test VALUES (‘2017-04-05 18:19:03')
看看他的 value 是什麼
還是 2017-04-05 18:19:03
「於2017/05/01 結束答題」

@YenChunchen
Copy link

YenChunchen commented May 1, 2017

「於2017/05/01 開始答題」

  1. UTC 是什麼?能表示時區嗎?
    最主要的世界時間標準,為國際通訊的公用標準,透過原子鐘模擬GMT,每隔一段時間多一個閏秒以接近GMT
  2. Timestamp 是什麼?能表示時區嗎?
    1970年1月1日0時0分0秒(GMT+0)到目前的總秒數,可以
    DB 能不能設定時區 (以 mysql 為例)
    可以:
  • 設定SQL全域時區:set global time_zone = [欲設定時區]';
  • 設定SQL當前session時區:set time_zone = '[欲設定時區]';
  • 查看SQL目前時區:show variables like "%time_zone%";
  1. 程式能不能設定時區 (以 nodejs 為例)
    不行:因為直接用Date()取得的是UTC+0的時間,但是可以透過程式去顯示某個時區的時間

  2. 系統能不能設定時區 (以 linux 為例)
    可以:sudo dpkg-reconfigure tzdata 後選取想要時區即可變更

  3. DB 內的日期時間欄位若存 string 和存 timestamp 和存 datetime 有什麼差別

  • string:可自由設定時間格式,但相對處理上需另外處理,可用STR_TO_DATE([字串],[格式])轉時間格式
  • timestamp:所佔位元較小,時間範圍較小,但可以依照時區改變
  • datetime:所佔位元較大,時間範圍較大,不可以依照時區改變
  1. Mysql 欄位格式 timestamp 和 datetime 的差別是什麼
  • timestamp:所佔位元較小,時間範圍較小,但可以依照時區改變
  • datetime:所佔位元較大,時間範圍較大,不可以依照時區改變
  1. 請問分別在伺服器上用 UTC 跟用本地時區的好處跟壞處在哪?
    若應用上皆在同一時區使用本地時區顯式上較清楚簡潔,但若需配合不同時區應用則用UTC才能清楚分辨該欄位正確時間
  2. 系統(伺服器)的時區設定是否會影響 DB 中的資料?
    DB的時間依照系統設定時間,故會影響
  3. (限mysql/mariadb)今天在 DB 中新增一個欄位,當時欄位型別是寫 boolean,但實際上開起來根本不是 boolean。這中間發生了什麼事情?
    mysql中的布林型態由tinyint表示,true,false,TRUE,FALSE,分别代表1,0,1,0
  4. 承上,實際上開的型別跟 boolean 是什麼關係? 一樣的,只是表示方式由1,0表示

@wildwindjen
Copy link
Contributor

wildwindjen commented May 7, 2017

因為第 4 題是「程式能不能設定時區」只是以 nodejs 為例。
題目我的理解是想問「程式層級能不能設定時區」

我要提醒一下,其實有的程式語言是可以設定程式層級的預設時區。
php, java 都可以。只是恰巧 javascript 看起來是不行。雖然好像可以利用套件或是一些取巧的做法,不過畢竟不是語言本身提供的。

亂聊一下我的理解:

「真實世界」

先說什麼是 UTC:
	世界協調時間,又稱世界標準時間或協調世界時,簡稱UTC(英文「Coordinated Universal Time」。是最主要的世界時間標準,其以原子時秒長為基礎,在時刻上儘量接近於格林威治標準時間(GMT),所以有閏秒。GMT 一開始是世界時間標準,但是誤差大(有的一天比較長,有的比較短,誤差值毫秒),所以由 UTC (誤差值奈秒)取代。

timezone	
	世界這麼大,各區域看到的太陽視角不一樣,所以「地方的時間」也會不同。所以出現了 timezone。代表的意義是跟標準經線差多少個小時。(還有理論時區、法定時區的差異。)

	https://www.timeanddate.com/time/map/

「電腦世界」

timestamp:
	為了模擬真實世界的時間,電腦世界定義了一個絕對值:「從協調世界時1970年1月1日0時0分0秒起至現在的總秒數,不包括閏秒。」 這個值,只要是「同一個時間點」,全世界不管你是在哪個地方都一樣。

	常見的表示方式是:
	1494127761

轉換成讓人看得懂:
	
	將 timestamp 直接給人類看就有點瞎了,它存在的意義我覺得是讓電腦好計算而已。

	電腦世界常見的表達格式:
	Sunday, 07-May-17 03:29:21 UTC 		(RFC 2822)
	Sun, 07 May 2017 03:29:21 +0000 	(RFC 822, 1036, 1123, 2822)
	2017-05-07T03:29:21+00:00 			(RFC 3339、ISO8601 格式)

	可以看到格式,其實已經隱含了「時區」的概念,上面代表的是在「時區 0」的地方時間(locale time)。
	在格式表達上,UTC 等於 +00:00。

	上述格式如果換成 Asia/Taipei (+8),就是
	Sun, 07 May 2017 11:29:21 +0800 	(RFC 822, 1036, 1123, 2822)
	2017-05-07T11:29:21+08:00 			(RFC 3339、ISO8601 格式)

	一旦告訴電腦目前的時間「2017-05-07 11:29:21」跟所在時區「+08:00」就能反推 timestamp。
	「2017-05-07T11:29:21+08:00」跟「2017-05-07T03:29:21+00:00」在電腦的世界裡,是一模一樣的 timestamp 值。

	timestamp 沒有 timezone 含義,因為他就是絕對值了,只有要「讓人看的格式」才有 timezone 存在的意義。 

	表達字串 = 轉換(timestamp, timezone)

回歸到題目,所謂的指定 timezone,都是應用在「當所在環境使用時間日期資訊時,需要轉換成表達字串,卻沒有清楚告知所用的 timezone 資訊,則預設採用的 timezone 設定」。

如果所在環境是作業系統層級,就拿作業系統的預設 timezone。
如果所在環境是 DB 就先查 DB 預設的,沒有 DB 預設的,DB server 可能會去拿作業系統的。
如果所在環境是程式層級.....。

timestamp data type 欄位存的是 timestamp 值,datetime 欄位,存的比較像是給人看的表達字串。所以當 DB 預設的 timezone 設定一旦改變,重新下 select 語法分別讀 timestamp/datetime 的值,就會看到這兩種欄位的差異了。

如果知道了上述的關係,就會知道什麼時候該關心 timezone,什麼時候不用。ex: 同時區的兩個人相差幾歲、不同時區的兩個人相差幾歲。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants