有出國經驗的同學都知道,國外時間跟台灣不一樣,有所謂「時區」,例如日本的時區快台灣一小時,而泰國慢台灣一小時。當台灣時間是上午9:00,在日本已經是 10:00,泰國則還在 8:00。
因為地球由西向東自轉,每個國家在地球不同位置,當台灣清晨看到第一縷陽光的時候,日本已經日出過了一小時,而泰國還處在黑夜,一小時後才會看到太陽。
全世界自1885年起,按所在地理位置,劃分為24個時區,並以英國格林威治天文臺時間為基準。例如台灣時區比格林威治標準時(Greenwich Mean Time, 簡稱 GMT)快8小時,表示為 GMT+8,而日本是 GMT+9,泰國是 GMT+7。
1982年之後改用 UTC (Universal Time Coordinated),基準時間改用原子鐘,比原來GMT標準更精準,但時區劃分大致相同,台灣是 UTC+8,日本是 UTC+9,泰國是 UTC+7。
全世界表達時間的形式,其實有很大不同,除了時區之外,還有一些地區使用獨特的「曆法」,例如台灣使用「民國」紀元,日本「平成」「令和」等年號,以及希伯來曆、印度曆、伊斯蘭曆等等,都仍在使用中,讓時間的表示形式變得複雜。
因此,Swift 時間有3個相關物件來解決這個問題:Date 儲存時間值,DateFormatter 可顯示本地格式,Calendar 用來轉換各地曆法。3個物件類型的關係如下圖:
Date 物件類型是最單純的,取得並儲存一個「相對時間值」,就是以格林威治時間2001/01/01 00:00:00為參考原點,相對所得的秒數,是一個實數(Double)值。
DateFormatter 則可依照本地格式,將 Date時間值轉換為字串,或是反過來,將字串轉為時間值。
Calendar 是用來轉換不同的曆法,或是用來取得年、月、日、時、分、秒等數值。
以下範例分別列印3個物件類型所產生的相關資料。
// 1-10c 曆法(Calendar)
// Revised by Heman, 2021/08/01
import Foundation
let 現在 = Date()
let 秒數 = 現在.timeIntervalSinceReferenceDate
print("現在離參考時間點已過\(秒數)秒")
var 本地格式 = DateFormatter()
本地格式.dateStyle = .full
本地格式.timeStyle = .long
print(本地格式.string(from: 現在))
let 年 = Calendar.current.component(.year, from: 現在)
let 月 = Calendar.current.component(.month, from: 現在)
let 日 = Calendar.current.component(.day, from: 現在)
let 星期 = Calendar.current.component(.weekday, from: 現在)
let 時 = Calendar.current.component(.hour, from: 現在)
let 分 = Calendar.current.component(.minute, from: 現在)
let 秒 = Calendar.current.component(.second, from: 現在)
let 星期幾 = ["日", "一", "二", "三", "四", "五", "六"]
print("現在本地時間是\(年)年\(月)月\(日)日 星期\(星期幾[星期-1]) \(時):\(分):\(秒)")
範例程式1-10c分為三段,分別列印 Date 現在離參考點的秒數、DateFormatter 顯示本地化的字串、以及 Calendar 將 Date 分解得到的年、月、日、時、分、秒整數值。
第一段
let 秒數 = 現在.timeIntervalSinceReferenceDate印出:現在離參考時間點已過649486547.089934秒,一年是3千多萬秒,現在離2001年已過了20年,所以是6億多秒。
print("現在離參考時間點已過\(秒數)秒")
第二段
var 本地格式 = DateFormatter()印出:2021年8月1日 星期日 GMT+8 下午12:55:47
本地格式.dateStyle = .full
本地格式.timeStyle = .long
print(本地格式.string(from: 現在))
第三段
let 年 = Calendar.current.component(.year, from: 現在)印出:現在本地時間是2021年8月1日 星期日 12:55:47
let 月 = Calendar.current.component(.month, from: 現在)
let 日 = Calendar.current.component(.day, from: 現在)
let 星期 = Calendar.current.component(.weekday, from: 現在)
let 時 = Calendar.current.component(.hour, from: 現在)
let 分 = Calendar.current.component(.minute, from: 現在)
let 秒 = Calendar.current.component(.second, from: 現在)
let 星期幾 = ["日", "一", "二", "三", "四", "五", "六"]
print("現在本地時間是\(年)年\(月)月\(日)日 星期\(星期幾[星期-1]) \(時):\(分):\(秒)")
Calendar.current 為目前使用的曆法,大部分電腦的預設是格里曆(西曆),要取得年月日時分秒等個別整數值,則是用 component 這個「方法」,輸入的第一個參數值要加句號 .,也就是 .year, .month 等等,是在物件中定義的,所以要加上句號(表示物件「的」)。
Calendar 所得到的 .weekday 數值是以 Sunday = 1, Monday = 2, ... Saturday = 7,這是格里曆的習慣,我們想列印出中文的星期,就需要用陣列做個轉換。