2022年7月19日 星期二

MS Sql Server 的 SYSDATETIMEOFFSET()、SWITCHOFFSET() 和 TODATETIMEOFFSET()

在 Microsoft Sql Server 中,
datetime 資料型別是沒有時區資訊的,,
比如 2022-01-01 00:00:00 如果沒有時區資訊的話,
它可以是美國時區的 2022-01-01 00:00:00 ,也可以是台灣時區的 2022-01-01 00:00:00,
對 1970-01-01 00:00:00 UTC+0 的毫秒數間隔是不一樣的。

而 datetimeoffset 資料型別就有時區資訊,
例如 2022-01-01 00:00:00 UTC+8 就是台灣時區的 2022-01-01 00:00:00,
對應到 UTC-8 的時區 就是 2001-12-31 08:00:00 UTC-8,
只是表示方式不同,
但對 1970-01-01 00:00:00 UTC+0 的毫秒數間隔通通都是一樣的。

以下介紹我常用的三個好用 Sql Server 函式,
SYSDATETIMEOFFSET()、SWITCHOFFSET() 和 TODATETIMEOFFSET(),
可以用來對日期格式做不同處理:

SYSDATETIMEOFFSET()
傳回擁有時區資訊的系統目前時間 (格式為 datetimeoffset(7),即小數位數有到 7 位的有時區時間)
例如 print SYSDATETIMEOFFSET() 可印出如下結果:
2022-07-19 20:40:24.8558075 -07:00
跟 SYSDATETIME() 的差別是 SYSDATETIME() 是傳回 datetime2 格式的無時區時間,其印出結果如下:
2022-07-19 20:40:24.8558075
可以看到只差在有無包含時區資訊而已

SWITCHOFFSET(datetimeoffset_expression, timezoneoffset_expression):
對特定有時區資訊 (沒給時區的話會被當做是 UTC+0) 的日期(datetimeoffset_expression) 用指定的時區位移(timezoneoffset_expression)
進行換算並返回相應的 dateoffset 型別結果,例如:
print SWITCHOFFSET('2022-01-01 03:00:00 +07:00', '+08:00')
的結果為:
2022-01-01 04:00:00.0000000 +08:00
可以看到 SWITCHOFFSET() 並不會改變日期的值,
也就是其日期和 1970-01-01 00:00:00 之間差距的毫秒數還是一樣,
指的還是同一個日期,只是用不同的時區格式寫出來而已。

TODATETIMEOFFSET(datetime_expression , timezoneoffset_expression):
對特定無時區資訊 (有給時區的話會被忽略) 的日期(datetime_expression) 加上指定的時區位移(timezoneoffset_expression)
資訊,返回日期和時區組合好後的有時區資訊日期,型別為 datetimeoffset,
例如:
print TODATETIMEOFFSET('2022-01-01 03:00:00 +07:00', '+08:00')
的結果為:
2022-01-01 03:00:00.0000000 +08:00
可以看到只有時區部份的資訊被改變了,表示無時區部份的日期資訊並沒有被改變,
所以其日期和 1970-01-01 00:00:00 之間差距的毫秒數也改變了,
變成用新時區去看日期部份得到的新日期。

參考資料:

  1. Transact-SQL (日期和時間資料類型和函式)
  2. 使用內建函式查詢

沒有留言 :

張貼留言