iOS关于时间的处理(一)—— 有关时间的基本知识

版本记录

版本号 时间
V1.0 2017.08.30

前言

app一定会和时间打交道,关于时间的处理有很多值得我们研究和注意的地方,时间是线性的,地球上各个时区的时间表示不一样,但是它们的绝对时间值是一样的,只是处于同一个时空我们对同一时间的表述或者理解不同罢了,这几篇就说一下关于时间的问题。

两种时间参考

1. GMT

人类对于时间的理解还很有限,但我们至少能确定一点:时间的变化是匀速的。时间前进的速度是均匀的,不会忽快忽慢,所以为了描述时间,我们也需要找到一个值,它的变化也是以均匀的速度向前变化的。

时间是线性匀速的,长久以来人们也是在找时间的参考物,前人发现抬头看太阳是个好办法,太阳总是按规律的“早起晚落”,而且“亘古不变”,可以用太阳在一天当中所处的位置来描述当前的时间。后来不同地区的文化需要交流,你这里太阳正高空照,我这可能已经下山了,所以需要有一个公共的大家都认可的地方,以这个地方太阳的位置来做参考着,沟通起来就会方便很多。最后选择的是英国伦敦的格林尼治天文台所在地,以格林尼治的时间作为公共时间,也就是我们所说的GMT时间(Greenwich Mean Time)

2. UTC

太阳所处的位置变化跟地球的自转相关,过去人们认为地球自转的速率是恒定的,但在1960年这一认知被推翻了,人们发现地球自转的速率正变得越来越慢,而时间前进的速率还是恒定的,所以GMT不再被认为可以用来精准的描述时间了。

我们需要继续寻找一个匀速前进的值。抬头看天是我们从宏观方向去寻找答案,科技的发展让我们在微观方面取得了更深的认识,于是有聪明人根据微观粒子原子的物理属性,建立了原子钟,以这种原子钟来衡量时间的变化,原子钟50亿年才会误差1秒,这种精读已经远胜于GMT了。这个原子钟所反映的时间,也就是我们现在所使用的UTC(Coordinated Universal Time )标准时间。


几种获取时间的方式

1. NSDate

先看一下它的开发文档。

NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001)

上面那一段翻译过来就是:NSDate对象封装单个时间点,与任何特定的日历系统或时区无关。 日期对象是不可变的,表示相对于绝对参考日期(2001年1月1日00:00:00 UTC)的不变时间间隔,它是以UTC为标准的。

下面看一下代码

- (void)demoTimeIntervalSinceReferenceDate
{
    NSDate *date = [NSDate date];
    NSLog(@"date = %lf", date.timeIntervalSinceReferenceDate);
}

下面看输出结果

2017-08-30 15:41:13.225921+0800 JJOC[1294:766001] date = 525771673.225875

下面我们计算一下: 525771673.225875/365/86400 = 16.6721104,今年是2017年,距离2001年正好是16年。

我们再看下面这个例子

- (void)demoDate
{
    NSDate *date = [NSDate date];
    NSLog(@"date = %@", date);
}

下面看输出结果

2017-08-30 15:44:54.197111+0800 JJOC[1301:767209] date = Wed Aug 30 15:44:54 2017

可见我这里输出的就是我当前的时间。

这里还要注意:NSDate是受手机系统时间控制的。也就是说,当你修改了手机上的时间显示,NSDate获取当前时间的输出也会随之改变。在我们做App的时候,明白这一点,就知道NSDate并不可靠,因为用户可能会修改它的值。

2. 函数CFAbsoluteTimeGetCurrent()

该函数出自Core Foundation框架,我们先看一下官方文档中的说明。

Absolute time is measured in seconds relative to the absolute reference date of Jan 1 2001 00:00:00 GMT. A positive value represents a date after the reference date, a negative value represents a date before it. For example, the absolute time -32940326 is equivalent to December 16th, 1999 at 17:54:34. Repeated calls to this function do not guarantee monotonically increasing results. The system time may decrease due to synchronization with external time references or due to an explicit user change of the clock.

这段文字翻译过来就是:相对于2001年1月1日00:00:00 GMT的绝对参考日期,绝对时间以秒为单位。 正值表示参考日期后的日期,负值表示其前的日期。 例如,绝对时间-32940326相当于1999年12月16日17:54:34。 对此功能的重复调用不能保证单调增加的结果。 由于与外部时间参考的同步或由于显式的用户更改时钟,系统时间可能会减少。

这里还要注意:CFAbsoluteTimeGetCurrent()也会跟着当前设备的系统时间一起变化,也可能会被用户修改。

3. 函数gettimeofday

还是先看一下API

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

该函数获取的时间是Unix time

Unix time是以UTC 1970年1月1号 00:00:00为基准时间,当前时间距离基准点偏移的秒数。

其实NSDate中也提供了获取这个时间的接口

- (void)demoTimeIntervalSince1970
{
    NSDate *date = [NSDate date];
    NSLog(@"date = %f", date.timeIntervalSince1970);
}

下面看输出结果

2017-08-30 16:02:54.282284+0800 JJOC[1307:770247] date = 1504080174.282267

同样,下面我们计算一下: 1504080174.282267/365/86400 = 47.694069444444445,今年是2017年,距离1970年正好是47年。

这里还要注意:gettimeofdayNSDateCFAbsoluteTimeGetCurrent()一样,都是受当前设备的系统时间影响。只不过是参考的时间基准点不一样而已。我们和服务器通讯的时候一般使用Unix time

4. mach_absolute_time()

我们需要找到一个均匀变化的属性值来描述时间,而在我们的iPhone上刚好有一个这样的值存在,就是CPU的时钟周期数(ticks)。这个tick的数值可以用来描述时间,而mach_absolute_time()返回的就是CPU已经运行的tick的数量。将这个tick数经过一定的转换就可以变成秒数,或者纳秒数,这样就和时间直接关联了。

不过这个tick数,在每次手机重启之后,会重新开始计数,而且iPhone锁屏进入休眠之后tick也会暂停计数。

这里要注意:mach_absolute_time()不会受系统时间影响,只受设备重启和休眠行为影响。

5. CACurrentMediaTime()

该函数是在QuartzCore框架中CABase.h中的函数。

/* Returns the current CoreAnimation absolute time. This is the result of
 * calling mach_absolute_time () and converting the units to seconds. */
CFTimeInterval CACurrentMediaTime (void)

CACurrentMediaTime()就是将上面mach_absolute_time()CPU tick数转化成秒数的结果。

下面看示例代码

- (void)demoCACurrentMediaTime
{
    double mediaTime = CACurrentMediaTime();
    NSLog(@"CACurrentMediaTime: %f", mediaTime);
}

下面看输出结果

2017-08-30 16:20:02.937803+0800 JJOC[1311:772292] CACurrentMediaTime: 194746.231819

这里输出的就是开机后设备一共运行了(设备休眠不统计在内)多少秒,另一个API也能返回相同的值。

- (void)demoSystemUptime
{
    NSTimeInterval systemUptime = [[NSProcessInfo processInfo] systemUptime];
    NSLog(@"systemUptime: %f", systemUptime);
}

看输出结果

2017-08-30 16:22:42.853656+0800 JJOC[1314:772878] systemUptime: 194906.147670

这里要注意:CACurrentMediaTime()也不会受系统时间影响,只受设备重启和休眠行为影响。

6. sysctl

该函数来自于下面的文件。

下面看代码

#include <sys/sysctl.h>
- (void)demoBootTime
{
    #define MIB_SIZE 2
    
    int mib[MIB_SIZE];
    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)
    {
        NSLog(@"time = %ld", boottime.tv_sec);
    }
}

下面看输出结果

2017-08-30 16:29:49.043262+0800 JJOC[1318:773969] time = 1503235239

返回的值是上次设备重启的Unix time

这里要注意:这个API返回的值也会受系统时间影响,用户如果修改时间,值也会随着变化。

参考文章

1. iOS关于时间的处理

后记

谢谢这个技术大牛的资料,关于时间以前并未碰到特别的需求也不会了解那么多,现在算是学到了不少了,未完,待续~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 转自:iOS关于时间的处理 做App避免不了要和时间打交道,关于时间的处理,里面有不少门道,远不是一行API调用,...
    咖啡绿茶1991阅读 687评论 0 0
  • 做App避免不了要和时间打交道,关于时间的处理,里面有不少门道,远不是一行API调用,获取当前系统时间这么简单。我...
    MrPeak阅读 4,609评论 0 42
  • 前言 在iOS开发过程中,经常会和时间打交道。例如用户在一个页面停留的时间、两个方法哪个执行更快等等。之前对于这部...
    WQ_UESTC阅读 3,270评论 0 12
  • 时间的概念 时间是线性的 均匀的, 同一时刻, 只有一个绝对只有一个时间值存在, 而时区的划分 只是为了方便而已 ...
    zh_19阅读 1,116评论 0 1
  • 在iOS开发中,经常会遇到各种各样的时间问题,8小时时差,时间戳,求时间间隔,农历等等。解决办法网上比比皆是,但大...
    真巧了_嘿阅读 2,758评论 0 7