需求
我們做客戶端的時候,有時會需要對客戶端與服務(wù)器的時間進行同步,比如搶購活動、倒計時等。這時我們要考慮如何準備地與服務(wù)器的時間進行同步,同時防止用戶本地的時間有誤差時導(dǎo)致的問題。
分析
描述
為了實現(xiàn)以上需求,我們需要:
獲取服務(wù)器某一時刻
A
的時間;記錄獲取到時刻
A
時的本地時間B
;需要用到時間時,獲取當前本地時間
C
,當C - B
作為時間間隔D
,則A + D
則是當前服務(wù)器的時間。
實現(xiàn)
從上面的步驟,我們可以得到,要消除用戶修改時間導(dǎo)致的影響,必須保證
B
和C
與系統(tǒng)時間無關(guān);iOS
中正好有提供這樣兩個接口:獲取設(shè)備當前時間
Now
,該值受系統(tǒng)時間影響,用戶如果修改時間,值也會隨著變化;獲取設(shè)備上次重啟的時間
BootTime
,該值受系統(tǒng)時間影響,用戶如果修改時間,值也會隨著變化;;由上面
iOS
提供的兩個接口,我們可以獲取本地時間B
、C
:設(shè)備自上次重啟后運行的時間(BootTime - Now
),該值與系統(tǒng)時間無關(guān);
代碼實現(xiàn)
獲取當前 Unix Time:
static func now() -> Int {
var now = timeval()
var tz = timezone()
gettimeofday(&now, &tz)
return now.tv_sec
}
獲取設(shè)備上次重啟的 Unix Time:
func boottime() -> Int {
var mid = [CTL_KERN, KERN_BOOTTIME]
var boottime = timeval()
var size = MemoryLayout.size(ofValue: boottime)
if sysctl(&mid, 2, &boottime, &size, nil, 0) != -1 {
return boottime.tv_sec
}
return 0
}
時間校準:
// 接口獲取服務(wù)器時間處理
let serverTime = xxx // 獲取到的服務(wù)器時間
let runTime0 = now() - boottime() // 當前設(shè)備運行時間
// 需要用到時間時
let runTime1 = now() - boottime() // 當前時刻設(shè)備運行時間
let currentTime = serverTime + (runTime1 - runTime0) // 當前服務(wù)器時間