iOS

iOS 日期时间那点儿事儿

2018-04-01  本文已影响236人  舌尖上的大胖

一、基本约定及要素

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

二、一些综合应用

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)

四、参考资料

(完)

上一篇 下一篇

猜你喜欢

热点阅读