一、NSCalendar
NSCalendar可以很方便的用来表示日期,获取日期的各种信息,包括年、月、日,时分秒。可以很方便的计算两个日期之前的关系。也可以很方便的根据一个日期获取另一个日期。
NSCalendar中有一个重要的概念NSCalendarUnit,这是一个位枚举,意味着作为参数可以采用位运算的方式传参。
typedef NS_OPTIONS(NSUInteger, NSCalendarUnit) {
// 公元前、公元后
NSCalendarUnitEra = kCFCalendarUnitEra,
// 获取年、月、日
NSCalendarUnitYear = kCFCalendarUnitYear,
NSCalendarUnitMonth = kCFCalendarUnitMonth,
NSCalendarUnitDay = kCFCalendarUnitDay,
// 获取时、分、秒
NSCalendarUnitHour = kCFCalendarUnitHour,
NSCalendarUnitMinute = kCFCalendarUnitMinute,
NSCalendarUnitSecond = kCFCalendarUnitSecond,
// 获取周几 周日为1 、周1为2
NSCalendarUnitWeekday = kCFCalendarUnitWeekday,
// 获取本周是本月的第几周,7天为1个单位
NSCalendarUnitWeekdayOrdinal = kCFCalendarUnitWeekdayOrdinal,
// 获取刻钟,15分钟为1刻钟
NSCalendarUnitQuarter API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0)) = kCFCalendarUnitQuarter,
// 本月第几周
NSCalendarUnitWeekOfMonth API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0)) = kCFCalendarUnitWeekOfMonth,
// 本年第几周
NSCalendarUnitWeekOfYear API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0)) = kCFCalendarUnitWeekOfYear,
NSCalendarUnitYearForWeekOfYear API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0)) = kCFCalendarUnitYearForWeekOfYear,
// 纳秒
NSCalendarUnitNanosecond API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0)) = (1 << 15),
NSCalendarUnitCalendar API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0)) = (1 << 20),
NSCalendarUnitTimeZone API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0)) = (1 << 21),
如下所示,使用上面的位组件,可以方便的获取一个时间的年月日等信息
NSDateComponents *comps = [NSCalendar.currentCalendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
另外一个比较重要的类是NSDateComponents,上面是通过位参数获取每个单位(年月日)的信息,返回的结构可以看到是一个NSDateComponents,如果我要表示一个日期的信息,构建日期或者进行日期的计算,就少不了NSDateComponents,它可以将日期按照单位的形式封装起来,然后通过NSCalendar的方法进行计算
NSDateComponents中表示日期的单位与上面的位枚举NSCalendarUnit基本类似,用的时候只需要新建并且赋值即可
// 构建一个日期
NSDateComponents *mycoms = [NSDateComponents new];
mycoms.year = 2018;
mycoms.month = 1;
mycoms.day = 3;
NSLog(@"%@", [NSCalendar.currentCalendar dateFromComponents:mycoms]);
// 如下:在当前日期加上3天
NSDateComponents *coms = [NSDateComponents new];
coms.day = 3;
NSDate *newDate = [NSCalendar.currentCalendar dateByAddingComponents:coms toDate:[NSDate date] options:0];
NSLog(@"%@", newDate);
了解NSCalendarUnit和NSDateComponents之后,再回过头看NSCalendar的初始化方法
NSCalendar提供了4中初始化方法
// 使用用户手机设置的日期信息,有缓存,用户手机日历改变后不会变
@property (class, readonly, copy) NSCalendar *currentCalendar;
// 使用用户手机设置的日期信息,并且用户改变之后会跟着改变
@property (class, readonly, strong) NSCalendar *autoupdatingCurrentCalendar API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)); // tracks changes to user's preferred calendar identifier
// 使用指定的标识获取日期,比如农历、佛历,常用的是格里高利历(NSCalendarIdentifierGregorian)
+ (nullable NSCalendar *)calendarWithIdentifier:(NSCalendarIdentifier)calendarIdentifierConstant API_AVAILABLE(macos(10.9), ios(8.0), watchos(2.0), tvos(9.0));
- (nullable id)initWithCalendarIdentifier:(NSCalendarIdentifier)ident NS_DESIGNATED_INITIALIZER;
NSCalendar中有一个属性firstWeekday,代表周几作为一周的开始。默认周日是一周的开始,如果设置firstWeekDay = 2,代表着周一作为一周的开始,但是设置了该值之后,并不会改变NSCalendarUnitWeekday的值,如果是周日,该值返回的还是1,并不是7。该值设置只会可以用于计算两个日期是否在同一周,比如按照之前的设置,周日、周一周六是同一周,如果设置周一是起始日,那么周一、周二周日才是同一周。同理,在计算今天一年的第几周时同样受改属性影响
NSCalendar可以方便的获取国际化的月份信息,比如英语一月标识为February。设置NSCalendar的NSLocale之后,使用属性monthSymbols可以获取全部的月份表示,这样做国际化处理的时候只要获取月份,然后从数组中取出对应的值即可
用来表示最小或者最大的范围,比如月份最小返回1~28,最大为1~31
- (NSRange)minimumRangeOfUnit:(NSCalendarUnit)unit;
- (NSRange)maximumRangeOfUnit:(NSCalendarUnit)unit;
用来表示大范围内的小范围的取值范围获取具体数值
// 当前时间对应的月份中有几天
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]].length;
// 当前时间对应的月份中有几周(前面说到的firstWeekday会影响到这个结果)
[[NSCalendar currentCalendar] rangeOfUnit:NSWeekCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]].length;
// 当前时间对应的周是当前年中的第几周
[[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekOfYearCalendarUnit inUnit:NSYearCalendarUnit forDate:self]; [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekCalendarUnit inUnit:NSYearCalendarUnit forDate:[NSDate date]];
// 当前时间对应的周是当前月中的第几周
[[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekOfMonthCalendarUnit inUnit:NSYearCalendarUnit forDate:self]; [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]];
判断给定日期是否为今天、昨天、明天或者周末
isDateInToday
isDateInYesterday
isDateInTomorrow
isDateInWeekend
计算两个日期之间的间隔,使用NSDateComponents表示
- (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSCalendarOptions)opts;
根据NSCalendarUnit比较两个时间
- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit
二、NSDate
要使用NSCalendar,离不开NSDate。
NSDate用来表示一个具体的时间,默认时区为0时区,在中国使用的是GMT+8,代表比0时区偏移8个小时。
在iOS中获取的时间都是基于0时区的,因此在中国获取的时间会少8个小时,需要使用下面的方式追加时间差值,或者使用NSDateFormatter的时候指定时区
// 得到当前时间(世界标准时间 UTC/GMT)
NSDate *date = [NSDate date];
// 设置系统时区为本地时区
NSTimeZone *zone = [NSTimeZone systemTimeZone];
// 计算本地时区与 GMT 时区的时间差
NSInteger interval = [zone secondsFromGMT];
// 在 GMT 时间基础上追加时间差值,得到本地时间
date = [date dateByAddingTimeInterval:interval];
三、NSTimeZone
用来表示时区信息
// 系统支持时区简写
abbreviationDictionary
四、NSLocale
用来表示本地化的相关信息.
每一个NSLocale实例对应着一个地区标识符,例如en_US,fr_FR,ja_JP和en_GB,这些标识符包含一个语言码(例如en代表英语)和一个地区码(例如US代表美国)
@property (class, readonly, copy) NSArray<NSString *> *ISOLanguageCodes;//所有ISO定义的语言编码`