iOS 日期时间那点儿事儿

一、基本约定及要素

现代系统对于日期时间的处理思想,是系统统一以 UTC 时间为准。在需要时,根据时区、日历、国际化/本地化等设置,依据 UTC 时间计算出所需要的时间,用于显示等操作。所以,理论上,世界上任何一台电脑,只要时钟是准的,获取到的 UTC 时间是一致的。只是系统会根据我们在电脑中设定的时区、日历、国际化/本地化等信息,再进行展示。
  iOS 中,主要涉及到的类如下:

  • NSDate
    主要用于日期的获取、存储、计算
  • NSDateComponents
    工具类,用于对于日期、时间的拆分、组装
  • NSCalendar
    日历,通过指定不同日历类型,来获取对应的信息。如:获取当前时间的农历月、日信息。
  • NSLocale
    区域化相关内容。此类不仅用于日期时间,本文只涉及日期时间的部分。
    如:获取当前时间月份的名称,区域为美国会显示 May,区域为中国会显示五月
  • NSTimeZone
    时区。用于配合 UTC 时间计算指定的时区对应的时间。
  • NSDateFormatter
    日期、时间格式化工具。格式化时,会根据用户指定的格式、时区、地区,进行处理。

二、一些综合应用

1、从字符串转化为时间

有些场景需要根据存储的字符串转换回时间。比如:HTTP 的 Response Header 的 Date 字段,格式为:Sun, 01 Apr 2018 01:18:07 GMT,需要转换回 NSDate,才便于后续处理。

- (NSDate *)dateFromString:(NSString *)dateStr {
    // 创建日期格式化工具
    NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
    // 指定日期格式,如上所示:Sun, 01 Apr 2018 01:18:07 GMT
    dateFormatter.dateFormat = @"EEE',' dd' 'MMM' 'yyyy HH':'mm':'ss 'GMT'";
    // 指定区域,这个很重要!EEE、MMM 会根据区域设置进行处理。如果这里设置为中文,则只能处理 “四月”、“周日”,而不能处理 “Apr”、“Sun”
    dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en"];
    // 指定所使用的是 UTC 时间
    dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];

    return [dateFormatter dateFromString:dateStr];
}

根据当前时间,格式化输出,操作类似。

2、获取当前时间的公历、农历日期

- (void)showDate {
    // 当前日期
    NSDate *date = [NSDate date];

    // 创建公历日历,此为默认值
    NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
    // 获取月、日
    NSDateComponents *dateComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
    NSLog(@"公历日期:%ld-%ld", dateComponents.month, dateComponents.day);

    // 创建中国农历日历
    calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierChinese];
    // 获取月、日
    dateComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
    NSLog(@"农历日期:%ld-%ld", dateComponents.month, dateComponents.day);
}

3、计算时间间隔

测试代码块耗时,单位:纳秒

#import <mach/mach_time.h>

CGFloat BNRTimeBlock (void (^block)(void)) {
    // 获取计时基础信息
    mach_timebase_info_data_t info;
    if (mach_timebase_info(&info) != KERN_SUCCESS) return -1.0;

    // 开始时间
    uint64_t start = mach_absolute_time ();

    // 执行代码块
    block ();

    // 结束时间
    uint64_t end = mach_absolute_time ();

    // 计算时间差
    uint64_t elapsed = end - start;

    // 根据系统“心率”计算时间
    uint64_t nanos = elapsed * info.numer / info.denom;
    return (CGFloat)nanos / NSEC_PER_SEC;
} // BNRTimeBlock

除此方法外,可以采用更为方便的 CACurrentMediaTime(),返回单位为秒。这个是对 mach_absolute_time() 的封装,使用起来更方便一些。

三、备查资料

1、NSTimeZone 初始化

使用 + timeZoneWithName:
获取已知的有效时区名称:NSTimeZone.knownTimeZoneNames,返回数组

注:北京时间在 iOS 的 TimeZone 对照表里面并没有,使用上海时间代表中国标准时
采用如下方式初始化即可:

// 初始化时区为 上海时间
[NSTimeZone timeZoneWithName:@"Asia/Shanghai"];

使用 + timeZoneWithAbbreviation:
获取有效缩写:[NSTimeZone abbreviationDictionary],返回字典

2、NSCalendar 初始化

// 公历
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
// 中国农历
calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierChinese];

具体日历类型,参见 NSCalendarIdentifier 类型。

3、NSDateFormatterStyle

typedef NS_ENUM(NSUInteger, NSDateFormatterStyle) {    // date and time format styles
    NSDateFormatterNoStyle = kCFDateFormatterNoStyle,
    NSDateFormatterShortStyle = kCFDateFormatterShortStyle,     // “11/23/37” or “3:30pm”.
    NSDateFormatterMediumStyle = kCFDateFormatterMediumStyle,   //“Nov 23, 1937”.or “3:30:32pm”.
    NSDateFormatterLongStyle = kCFDateFormatterLongStyle,       //“November 23, 1937” or “3:30:32pm”.  GMT+08:00
    NSDateFormatterFullStyle = kCFDateFormatterFullStyle        //“Tuesday, April 12, 1952 AD” or “3:30:42pm PST”.
};

这里假设的是区域设置为美国的情况,具体的格式,还跟 locale 设置有关。

常见 dateFormat
符号 说明
a AM/PM (上午/下午)
c/cc 1~7 (一周的第一天, 周日为1)
ccc Sun/Mon/Tue/Wed/Thu/Fri/Sat (星期几简写)
cccc Sunday/Monday/Tuesday/Wednesday/Thursday/Friday/Saturday (星期几全拼)
d 1~31 (月份的第几天, 带0)
D 1~366 (年份的第几天,带0)
e 1~7 (一周的第几天, 带0)
E~EEE Sun/Mon/Tue/Wed/Thu/Fri/Sat (星期几简写)
EEEE Sunday/Monday/Tuesday/Wednesday/Thursday/Friday/Saturday (星期几全拼)
F 1~5 (每月的第几周, 一周的第一天为周一)
h 1~12 (0 padded Hour (12hr)) 带0的时, 12小时制
H 0~23 (0 padded Hour (24hr)) 带0的时, 24小时制
m 0~59 (0 padded Minute) 分钟
M/MM 1~12 (0 padded Month) 第几月
MMM Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec
MMMM January/February/March/April/May/June/July/August/September/October/November/December
s 0~59 (0 padded Second) 秒数
SSS (rounded Sub-Second) 毫秒
w 1~53 (0 padded Week of Year, 1st day of week = Sunday, NB: 1st week of year starts from the last Sunday of last year) 一年的第几周, 一周的开始为周日,第一周从去年的最后一个周日起算
W 1~5 (0 padded Week of Month, 1st day of week = Sunday) 一个月的第几周
y/yyyy (Full Year) 完整的年份
yy/yyy (2 Digits Year) 2个数字的年份
Y/YYYY (Full Year, starting from the Sunday of the 1st week of year) 这个年份未知干嘛用的
YY/YYY (2 Digits Year, starting from the Sunday of the 1st week of year) 这个年份未知干嘛用的
z~zzz (Specific GMT Timezone Abbreviation) 指定GMT时区的编写
zzzz (Specific GMT Timezone Name) Z: +0000 (RFC 822 Timezone) 指定GMT时区的名称

详见
Date Format Patterns
Date Field Symbol Table

4、时间进制换算

1 秒(s) == 1000 毫秒(ms)
1 毫秒(ms) == 1000 微秒(μs)
1 微秒(μs) == 1000 纳秒(ns)

四、参考资料

(完)

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

推荐阅读更多精彩内容