iOS中的時間

時間的概念

時間是線性的 均勻的, 同一時刻, 只有一個絕對只有一個時間值存在, 而時區(qū)的劃分 只是為了方便而已

GMT(Greenwich Mean Time)

在狹義的范圍下 時間的變化是勻速的, 為了描述時間, 我們也需要找到一個值,它的變化時均勻的, 最終選擇了太陽 按照太陽在一天當中所處的位置來描述當前時間, 但不同的地區(qū)太陽的位置并不一樣, 后來不同地區(qū)的文化為了交流方便, 選取了一個公共的大家認可的地方, 以這個地方太陽的位置來作參考, 最后選擇的是英國倫敦的格林尼治天文臺所在地,以格林尼治的時間作為公共時間,也就是我們所說的GMT時間

UTC(Coordinated Universal Time)

太陽所處的位置變化跟地球的自轉(zhuǎn)相關(guān),過去人們認為地球自轉(zhuǎn)的速率是恒定的,但在1960年這一認知被推翻了,人們發(fā)現(xiàn)地球自轉(zhuǎn)的速率正變得越來越慢,而時間前進的速率還是恒定的,所以GMT不再被認為可以用來精準的描述時間了。

我們需要繼續(xù)尋找一個勻速前進的值。抬頭看天是我們從宏觀方向去尋找答案,科技的發(fā)展讓我們在微觀方面取得了更深的認識,于是有聰明人根據(jù)微觀粒子原子的物理屬性,建立了原子鐘,以這種原子鐘來衡量時間的變化,原子鐘50億年才會誤差1秒,這種精讀已經(jīng)遠勝于GMT了。這個原子鐘所反映的時間,也就是我們現(xiàn)在所使用的UTC(Coordinated Universal Time )標準時間。

NSDate

NSDate對象描述的是時間線上的一個絕對的值,和時區(qū)和文化無關(guān),它參考的值是:以UTC為標準的,2001年一月一日00:00:00這一刻的時間絕對值。
這里有個概念很重要,我們用編程語言描述時間的時候,都是以一個時間線上的絕對值為參考點,參考點再加上偏移量(以秒或者毫秒,微秒,納秒為單位)來描述另外的時間點。

理解了這一點,再看NSDate的一些API調(diào)用就非常清楚了,比如:

NSDate* date = [NSDate date];
NSLog(@"current date: %@", date);
NSLog(@"current date interval: %f", [date timeIntervalSinceReferenceDate]);

NSDate和市區(qū)和文化無關(guān),所以要展示具體格式的時間,我們需要NSDateFormatter和NSTimeZone的輔助。

另外關(guān)于NSDate最重要的一點是:NSDate是受手機系統(tǒng)時間控制的。也就是說,當你修改了手機上的時間顯示,NSDate獲取當前時間的輸出也會隨之改變。在我們做App的時候,明白這一點,就知道NSDate并不可靠,因為用戶可能會修改它的值。

CFAbsoluteTimeGetCurrent()

CFAbsoluteTimeGetCurrent()的概念和NSDate非常相似,只不過參考點是:以GMT為標準的,2001年一月一日00:00:00這一刻的時間絕對值。

同樣CFAbsoluteTimeGetCurrent()也會跟著當前設(shè)備的系統(tǒng)時間一起變化,也可能會被用戶修改。

gettimeofday

struct timeval now;
struct timezone tz;
gettimeofday(&now, &tz);
NSLog(@"gettimeofday: %ld", now.tv_sec);

使用gettimeofday獲得的值是Unix time。Unix time又是什么呢?

Unix time是以UTC 1970年1月1號 00:00:00為基準時間,當前時間距離基準點偏移的秒數(shù)。上述API返回的值是1481266031,表示當前時間距離UTC 1970年1月1號 00:00:00一共過了1481266031秒。
NSDate也有一個API能返回Unix time

NSDate* date = [NSDate date];
NSLog(@"timeIntervalSince1970: %f", [date timeIntervalSince1970]);

gettimeofday和NSDate,CFAbsoluteTimeGetCurrent()一樣,都是受當前設(shè)備的系統(tǒng)時間影響。只不過是參考的時間基準點不一樣而已。我們和服務(wù)器通訊的時候一般使用Unix time。

mach_absolute_time()

前面提到我們需要找到一個均勻變化的屬性值來描述時間,而在我們的iPhone上剛好有一個這樣的值存在,就是CPU的時鐘周期數(shù)(ticks)。這個tick的數(shù)值可以用來描述時間,而mach_absolute_time()返回的就是CPU已經(jīng)運行的tick的數(shù)量。將這個tick數(shù)經(jīng)過一定的轉(zhuǎn)換就可以變成秒數(shù),或者納秒數(shù),這樣就和時間直接關(guān)聯(lián)了。

不過這個tick數(shù),在每次手機重啟之后,會重新開始計數(shù),而且iPhone鎖屏進入休眠之后tick也會暫停計數(shù)。

mach_absolute_time()不會受系統(tǒng)時間影響,只受設(shè)備重啟和休眠行為影響。

CACurrentMediaTime()

CACurrentMediaTime()就是將上面mach_absolute_time()的CPU tick數(shù)轉(zhuǎn)化成秒數(shù)的結(jié)果。以下代碼:

double mediaTime = CACurrentMediaTime();
NSLog(@"CACurrentMediaTime: %f", mediaTime);

返回的就是開機后設(shè)備一共運行了(設(shè)備休眠不統(tǒng)計在內(nèi))多少秒,另一個API也能返回相同的值:

NSTimeInterval systemUptime = [[NSProcessInfo processInfo] systemUptime];
NSLog(@"systemUptime: %f", systemUptime);

CACurrentMediaTime()也不會受系統(tǒng)時間影響,只受設(shè)備重啟和休眠行為影響。

sysctl

iOS系統(tǒng)記錄了上次設(shè)備重啟的時間. 可以通過如下API調(diào)用獲取:

#include <sys/sysctl.h>

- (long)bootTime
{
    int mib[2];
    size_t size;
    struct timeval  boottime;
    
    mib[0] = CTL_KERN;
    mib[1] = KERN_BOOTTIME;
    size = sizeof(boottime);
    if (sysctl(mib, MIB_SIZE, &boottime, &size, NULL, 0) != -1)
    {
        return boottime.tv_sec;
    }
    return 0;
}

返回的值是上次設(shè)備重啟的Unix time。

這個API返回的值也會受系統(tǒng)時間影響,用戶如果修改時間,值也會隨著變化。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS開發(fā)中,經(jīng)常會遇到各種各樣的時間問題,8小時時差,時間戳,求時間間隔,農(nóng)歷等等。解決辦法網(wǎng)上比比皆是,但大多...
    小李龍彪閱讀 6,741評論 1 6
  • 轉(zhuǎn)自:iOS關(guān)于時間的處理 做App避免不了要和時間打交道,關(guān)于時間的處理,里面有不少門道,遠不是一行API調(diào)用,...
    咖啡綠茶1991閱讀 733評論 0 0
  • 做App避免不了要和時間打交道,關(guān)于時間的處理,里面有不少門道,遠不是一行API調(diào)用,獲取當前系統(tǒng)時間這么簡單。我...
    MrPeak閱讀 4,711評論 0 42
  • 前言 在iOS開發(fā)過程中,經(jīng)常會和時間打交道。例如用戶在一個頁面停留的時間、兩個方法哪個執(zhí)行更快等等。之前對于這部...
    WQ_UESTC閱讀 3,536評論 0 12
  • 版本記錄 前言 做app一定會和時間打交道,關(guān)于時間的處理有很多值得我們研究和注意的地方,時間是線性的,地球上各個...
    刀客傳奇閱讀 1,603評論 0 1

友情鏈接更多精彩內(nèi)容