前言
在iOS中我們經(jīng)常需要使用到時(shí)間戳,但在iOS下獲取“時(shí)間”的方法有很多。不過總的來說,我們可以在iOS中獲取的時(shí)間戳主要有兩類----絕對時(shí)間與相對時(shí)間。下面將總結(jié)一下這些方法之間的關(guān)系。
1、絕對時(shí)間
絕對時(shí)間是指那些以固定時(shí)間為參考系的時(shí)間戳。
常用的有Foundation框架中的
[[NSDate date] timeIntervalSinceReferenceDate];
以及CoreFoundation框架中的
CFAbsoluteTimeGetCurrent();
上述兩種方法是等價(jià)的,所參考的起始時(shí)間都是世界時(shí)間(UTC)2001年1月1日凌晨,所返回的double類型的結(jié)果都是從參考時(shí)間至今經(jīng)過的秒數(shù)。
除了剛才提到的參考時(shí)間,還有以世界時(shí)間(UTC)1970年1月1日凌晨為參考系的
[[NSDate date] timeIntervalSince1970];
//打印結(jié)果
NSLog(@"%f", CFAbsoluteTimeGetCurrent());
NSLog(@"%f", [[NSDate date] timeIntervalSinceReferenceDate]);
NSLog(@"%f", [[NSDate date] timeIntervalSince1970]);
2016-11-29 10:50:35.737 TidusWWDemo[192:4266] 502080635.736519
2016-11-29 10:50:35.740 TidusWWDemo[192:4266] 502080635.740338
2016-11-29 10:50:35.740 TidusWWDemo[192:4266] 1480387835.740696
由于參考系是固定的,顯然每次通過這些方法獲取的時(shí)間戳都將是不同的。但絕對不變的參考系并不意味著絕對可靠的結(jié)果,實(shí)際上當(dāng)用戶手動(dòng)改變了設(shè)備上的系統(tǒng)時(shí)間后,基于系統(tǒng)時(shí)鐘的上述方法返回的結(jié)果也會一同改變。
假如我們想獲取一種不會被用戶手動(dòng)修改而影響的時(shí)間戳,該怎么辦?答案是相對時(shí)間。
2、相對時(shí)間
相對時(shí)間是指以非固定時(shí)間為參考系返回的時(shí)間戳
常用的有Foundation框架中的
[[NSProcessInfo processInfo] systemUptime];
和QuartzCore框架中的
CACurrentMediaTime();
//打印結(jié)果(一臺剛重啟沒多久的設(shè)備)
NSTimeInterval systemUptime = [[NSProcessInfo processInfo] systemUptime];
CFTimeInterval currentTime = CACurrentMediaTime();
NSLog(@"%f", systemUptime);
NSLog(@"%f", currentTime);
2016-11-29 10:50:35.762 TidusWWDemo[192:4266] 487.083420
2016-11-29 10:50:35.762 TidusWWDemo[192:4266] 487.099180
上面兩種方法獲取到的都是設(shè)備自最近一次啟動(dòng)至今經(jīng)過的時(shí)間戳。CFAbsoluteTimeGetCurrent()
方法調(diào)用底層的mach_absolute_time()
方法后將結(jié)果轉(zhuǎn)換成秒返回。該結(jié)果是設(shè)備自最近一次啟動(dòng)至今經(jīng)過的時(shí)間,不隨系統(tǒng)時(shí)間改變而改變,但當(dāng)設(shè)備重啟后,該方法返回的結(jié)果也會重置。
3、優(yōu)劣
兩類時(shí)間戳都有各自的特點(diǎn):
絕對時(shí)間參考固定的時(shí)間點(diǎn)返回時(shí)間戳但結(jié)果會受系統(tǒng)時(shí)鐘的影響;
相對時(shí)間在設(shè)備不重啟的情況下總能正確返回某一時(shí)間段內(nèi)流逝的時(shí)間;
所以具體要使用哪種方法獲取時(shí)間戳需要結(jié)合不同的需求場景去選擇。
4、NSDate
獲取到了時(shí)間戳,也許我們需要利用它來轉(zhuǎn)換為時(shí)間并以一定的格式去展示,NSDate轉(zhuǎn)NSString的方法網(wǎng)上有很多,在這里就不再敘述。需要注意的一點(diǎn)是,獲取到絕對時(shí)間戳是以世界時(shí)間(UTC)為準(zhǔn)的,NSDate中保存的日期也是以世界時(shí)間(UTC)為準(zhǔn)的,所以在通過NSDateFormatter轉(zhuǎn)換為NSString的時(shí)候一定要注意當(dāng)前的時(shí)區(qū)。
NSTimeInterval intervalSince1970 = [[NSDate date] timeIntervalSince1970];
NSDate *date = [NSDate dateWithTimeIntervalSince1970:intervalSince1970];
NSLog(@"date中保存的是UTC時(shí)間:%@", date);
//顯示時(shí)需要注意時(shí)區(qū)
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];
//設(shè)置時(shí)區(qū)
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"zh"]];
NSString *datestring = [formatter stringFromDate:date];
NSLog(@"北京所在時(shí)區(qū)為東八區(qū):%@", detesting);
//打印結(jié)果
2016-11-30 15:35:40.078 TidusWWDemo[59040:21040031] date中保存的是UTC時(shí)間:2016-11-30 07:35:40 +0000
2016-11-30 15:35:40.079 TidusWWDemo[59040:21040031] 北京所在時(shí)區(qū)為東八區(qū):2016-11-30 15:35:40 GMT+8
5、最后
如果App本身對獲取的時(shí)間精度要求很高,還是直接通過網(wǎng)絡(luò)從服務(wù)器獲取時(shí)間戳?xí)容^保險(xiǎn)。當(dāng)網(wǎng)絡(luò)可用時(shí),直接從服務(wù)器獲取;網(wǎng)絡(luò)不可用時(shí),且設(shè)備沒有被重啟過,可以根據(jù)上一次獲取服務(wù)器時(shí)間戳的時(shí)刻到此時(shí)的時(shí)間差來推算出正確的時(shí)間。