需求
我們做客戶端的時(shí)候逢捺,有時(shí)會(huì)需要對(duì)客戶端與服務(wù)器的時(shí)間進(jìn)行同步筑悴,比如搶購(gòu)活動(dòng)们拙、倒計(jì)時(shí)等。這時(shí)我們要考慮如何準(zhǔn)備地與服務(wù)器的時(shí)間進(jìn)行同步阁吝,同時(shí)防止用戶本地的時(shí)間有誤差時(shí)導(dǎo)致的問題砚婆。
分析
描述
為了實(shí)現(xiàn)以上需求,我們需要:
獲取服務(wù)器某一時(shí)刻
A
的時(shí)間求摇;記錄獲取到時(shí)刻
A
時(shí)的本地時(shí)間B
射沟;需要用到時(shí)間時(shí),獲取當(dāng)前本地時(shí)間
C
与境,當(dāng)C - B
作為時(shí)間間隔D
验夯,則A + D
則是當(dāng)前服務(wù)器的時(shí)間。
實(shí)現(xiàn)
從上面的步驟摔刁,我們可以得到挥转,要消除用戶修改時(shí)間導(dǎo)致的影響,必須保證
B
和C
與系統(tǒng)時(shí)間無關(guān)共屈;iOS
中正好有提供這樣兩個(gè)接口:獲取設(shè)備當(dāng)前時(shí)間
Now
绑谣,該值受系統(tǒng)時(shí)間影響,用戶如果修改時(shí)間拗引,值也會(huì)隨著變化借宵;獲取設(shè)備上次重啟的時(shí)間
BootTime
,該值受系統(tǒng)時(shí)間影響矾削,用戶如果修改時(shí)間壤玫,值也會(huì)隨著變化;哼凯;由上面
iOS
提供的兩個(gè)接口欲间,我們可以獲取本地時(shí)間B
、C
:設(shè)備自上次重啟后運(yùn)行的時(shí)間(BootTime - Now
)断部,該值與系統(tǒng)時(shí)間無關(guān)猎贴;
代碼實(shí)現(xiàn)
獲取當(dāng)前 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
}
時(shí)間校準(zhǔn):
// 接口獲取服務(wù)器時(shí)間處理
let serverTime = xxx // 獲取到的服務(wù)器時(shí)間
let runTime0 = now() - boottime() // 當(dāng)前設(shè)備運(yùn)行時(shí)間
// 需要用到時(shí)間時(shí)
let runTime1 = now() - boottime() // 當(dāng)前時(shí)刻設(shè)備運(yùn)行時(shí)間
let currentTime = serverTime + (runTime1 - runTime0) // 當(dāng)前服務(wù)器時(shí)間