NSDateComponents和NSCalendar释义

NSDateComponents封装了具体年月日、时秒分、周、季度等

一、NSDateComponents相关方法:

1. NSCalendar对象的 - (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)date

取得一个NSDate对象的1个或多个部分,用NSDateComponents来封装

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [NSDate date];

//NSDateComponents *compt = [calendar components:NSDayCalendarUnit fromDate:date];

NSDateComponents *compt = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:date];

NSLog(@"%d,%@",[compt year],date);

NSLog(@"%d,%@",[compt month],date);

NSLog(@"%d,%@",[compt day],date);

需要注意的是,只有明确指定了unitFlags,NSDateComponents相应的那一部分才有值。

2. NSCalendar对象的 - (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options : (NSUInteger)opts

取得两个NSDate对象的时间间隔,用NSDateComponents来封装

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [NSDate date];

NSDate *date2 = [NSDate dateWithTimeInterval:5*60*60+75sinceDate:date];

NSDateComponents *compt = [calendar components:(NSMinuteCalendarUnit|NSSecondCalendarUnit) fromDate:date toDate:date2 options:0];

NSLog(@"%d",[compt minute]);

NSLog(@"%d",[compt second]);

有几点需要注意:

①得到的NSDateComponents对象可能会包含负数。例如:当toDate比fromDate晚10秒,second部分返回10;当toDate比fromDate早10秒,second部分返回-10

② 当指定unitFlags返回多个部分时,相隔的时间由多个部分共同组成(而不是独立去表示)。例如:上面的例子时间相差5小时1分15秒,如果指定只返回second部分,将得到18075秒;如果指定返回minute和second部分,将得到301分15秒;如果指定返回hour、minute和second,将得到5小时1分15秒。

3. NSCalendar对象的 - (NSDate *)dateFromComponents:(NSDateComponents *)comps

根据NSDateComponents对象得到一个NSDate对象

NSDateComponents *compt = [[NSDateComponents alloc] init];

[compt setYear:2012];

[compt setMonth:5];

[compt setDay:11];

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [calendar dateFromComponents:compt];

//得到本地时间,避免时区问题

NSTimeZone *zone = [NSTimeZone systemTimeZone];

NSInteger interval = [zone secondsFromGMTForDate:date];

NSDate *localeDate = [date dateByAddingTimeInterval:interval];

NSLog(@"%@",localeDate);

4. NSCalendar对象的 - (NSDate *)dateByAddingComponents:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts

在参数date基础上,增加一个NSDateComponents类型的时间增量

NSDateComponents *compt = [[NSDateComponents alloc] init];

[compt setDay:25];

[compt setHour:4];

[compt setMinute:66];

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [calendar dateByAddingComponents:compt toDate:[NSDate date] options:0];


//得到本地时间,避免时区问题

NSTimeZone *zone = [NSTimeZone systemTimeZone];

NSInteger interval = [zone secondsFromGMTForDate:date];

NSDate *localeDate = [date dateByAddingTimeInterval:interval];

NSLog(@"%@",localeDate);

当前时间的基础上,增加25天4小时66秒


二、NSCalendar

1. + (id)currentCalendar / + (id)autoupdatingCurrentCalendar

这两个类方法都将返回当前客户端的逻辑日历,区别在于:currentCalendar取得的值会一直保持在cache中,第一次用此方法实例化对象后,即使修改了系统日历设定,这个对象也不会改变。而使用autoupdatingCurrentCalendar,当每次修改系统日历设定,其实例化的对象也会随之改变。

下面的代码演示了区别所在,假设初始Calendar设定为NSGregorianCalendar(公历),先用这两个函数分别初始化两个对象,然后修改系统日历为NSJapaneseCalendar(日本和历),再重新打印这两个对象的信息:

NSCalendar *calendar;

NSCalendar *calendar2;

- (IBAction)doTest:(id)sender 

{

    calendar = [NSCalendar currentCalendar];

    calendar2 = [NSCalendar autoupdatingCurrentCalendar];


    NSLog(@"%@",calendar.calendarIdentifier);//print "gregorian"

    NSLog(@"%@",calendar2.calendarIdentifier);//print "gregorian"

}

- (IBAction)doAgain:(id)sender 

{

    NSLog(@"%@",calendar.calendarIdentifier);//print "gregorian"

    NSLog(@"%@",calendar2.calendarIdentifier);//print "japanese"

}

2. - (id)initWithCalendarIdentifier:(NSString *)string

根据提供的日历标示符初始化

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSChineseCalendar];

NSLog(@"%@",calendar.calendarIdentifier);

系统中定义的日历有:

NSGregorianCalendar --公历

NSBuddhistCalendar --佛教日历

NSChineseCalendar --中国农历

NSHebrewCalendar --希伯来日历

NSIslamicCalendar --伊斯兰历

NSIslamicCivilCalendar --伊斯兰教日历

NSJapaneseCalendar --日本日历

NSRepublicOfChinaCalendar --中华民国日历(台湾)

NSPersianCalendar --波斯历

NSIndianCalendar --印度日历

NSISO8601Calendar -- ISO8601

NSCalendar常用对象方法与类方法:

1. - (void)setLocale:(NSLocale *)locale

设置本地化信息

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

[calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];

NSLog(@"%@",calendar.locale.localeIdentifier);

2. - (void)setTimeZone:(NSTimeZone *)tz

设置时区信息

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"HKT"]];

NSLog(@"%@",calendar.timeZone);

3. - (void)setFirstWeekday:(NSUInteger)weekday

设置每周的第一天从星期几开始,比如:1代表星期日开始,2代表星期一开始,以此类推。默认值是1

如图所示,如果从星期天开始,日历的表现形式:

如果从星期二开始,日历的表现形式:

NSCalendar *calendar = [NSCalendar currentCalendar];

[calendar setFirstWeekday:3];

NSLog(@"%i",calendar.firstWeekday);

4. - (void)setMinimumDaysInFirstWeek:(NSUInteger)mdw

设置每年及每月第一周必须包含的最少天数,比如:设定第一周最少包括3天,则value传入3

NSCalendar *calendar = [NSCalendar currentCalendar];

[calendar setMinimumDaysInFirstWeek:3];

NSLog(@"%i",calendar.minimumDaysInFirstWeek);

5. - (NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date

获取一个小的单位在一个大的单位里面的序数

NSCalendarUnit包含的值有:

NSEraCalendarUnit --纪元单位。对于NSGregorianCalendar(公历)来说,只有公元前(BC)和公元(AD);而对于其它历法可能有很多,例如日本和历是以每一代君王统治来做计算。

NSYearCalendarUnit --年单位。值很大,相当于经历了多少年,未来多少年。

NSMonthCalendarUnit --月单位。范围为1-12

NSDayCalendarUnit --天单位。范围为1-31

NSHourCalendarUnit --小时单位。范围为0-24

NSMinuteCalendarUnit --分钟单位。范围为0-60

NSSecondCalendarUnit --秒单位。范围为0-60

NSWeekCalendarUnit --周单位。范围为1-53

NSWeekdayCalendarUnit --星期单位,每周的7天。范围为1-7

NSWeekdayOrdinalCalendarUnit --没完全搞清楚

NSQuarterCalendarUnit --几刻钟,也就是15分钟。范围为1-4

NSWeekOfMonthCalendarUnit --月包含的周数。最多为6个周

NSWeekOfYearCalendarUnit --年包含的周数。最多为53个周

NSYearForWeekOfYearCalendarUnit --没完全搞清楚

NSTimeZoneCalendarUnit --没完全搞清楚

下面是一些示例:

①当小单位为NSWeekdayCalendarUnit,大单位为NSWeekCalendarUnit时(即某个日期在这一周是第几天),根据firstWeekday属性不同,返回的结果也不同。

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:10];   

//[calendar setFirstWeekday:2];

intcount = [calendar ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:date];

NSLog(@"%d",count);

默认firstWeekday为1(星期天开始)的情况下,得到的结果是2,从下图可以看到是第2天。

假如firstWeekday被设置为2(星期一开始)的情况下,得到的结果是1,从下图可以看到是第1天

②当小单位为NSWeekCalendarUnit,大单位为NSYearCalendarUnit时(即某个日期在这一年中是第几周),根据minimumDaysInFirstWeek属性不同,返回的结果也不同。

NSDateComponents *compt = [[NSDateComponents alloc] init];

[compt setYear:2013];

[compt setMonth:1];

[compt setDay:20];

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [calendar dateFromComponents:compt];

//[calendar setMinimumDaysInFirstWeek:6];

intcount = [calendar ordinalityOfUnit:NSWeekCalendarUnit inUnit:NSYearCalendarUnit forDate:date];

NSLog(@"%d",count);

从上图的日历中可以看出,在没有设置minimumDaysInFirstWeek的情况下,1月20日得到的结果是4(第四个周)。

默认情况下第一个周有5天,如果将minimumDaysInFirstWeek设置为6天,则原本是第一周的1月1日--1月5日被划分到了上一年,返回0;而1月6日--1月12日升为第一周,1月13日--1月19日升为第二周。。依此类推。

所以需要关注的是minimumDaysInFirstWeek与实际第一周包含天数的大小比较,如果提供的minimumDaysInFirstWeek比实际第一周的天数小,则一切不变;否则统计"一年中第几周"、"一个月中第几周"会产生变化。

6. - (NSRange)rangeOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date

根据参数提供的时间点,得到一个小的单位在一个大的单位里面的取值范围

NSDateComponents *compt = [[NSDateComponents alloc] init];

[compt setYear:2013];

[compt setMonth:2];

[compt setDay:21];

[compt setHour:9];

[compt setMinute:45];

[compt setSecond:30];

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [calendar dateFromComponents:compt];

//得到本地时间,避免时区问题

NSTimeZone *zone = [NSTimeZone systemTimeZone];

NSInteger interval = [zone secondsFromGMTForDate:date];

NSDate *localeDate = [date dateByAddingTimeInterval:interval];

NSRange range = [calendar rangeOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:localeDate];

NSLog(@"%d -- %d",range.location,range.length);

调用这个方法要明确一点,取得的是"范围"而不是"包含",下面是一些例子:

① 小单位是NSDayCalendarUnit,大单位是NSYearCalendarUnit,并不是要取这一年包含多少天,而是要取"天"(Day)这个单位在这一年(Year)的取值范围。其实不管你提供的日期是多少,返回的值都是"1--31"。

②小单位是NSDayCalendarUnit,大单位是NSMonthCalendarUnit。要取得参数时间点所对应的月份下,"天"(Day)的取值范围。根据参数时间的月份不同,值也不同。例如2月是1--28、3月是1--31、4月是1--30。

③小单位是NSWeekCalendarUnit,大单位是NSMonthCalendarUnit。要取得参数时间点所对应的月份下,"周"(Week)的取值范围。需要注意的是结果会受到minimumDaysInFirstWeek属性的影响。在默认minimumDaysInFirstWeek情况下,取得的范围值一般是"1--5",从日历上可以看出来这个月包含5排,即5个周。

④小单位是NSDayCalendarUnit,大单位是NSWeekCalendarUnit。要取得周所包含的"天"(Day)的取值范围。下面是一个示例日历图:

在上图的日期条件下,假如提供的参数是4月1日--4月6日,那么对应的week就是1(第一个周),可以看到第一个周包含有6天,从1号开始,那么最终得到的范围值为1--6。

假如提供的参数是4月18日,那么对应的week是3(第三个周),第三个周包含有7天,从14号开始,那么最终得到的范围值是14--7。

假如提供的参数是4月30日,那么对应的week是5(第五个周),第五个周只包含3天,从28号开始,那么最终得到的范围值是28--3。

7. - (BOOL)rangeOfUnit:(NSCalendarUnit)unit startDate:(NSDate **)datep interval:(NSTimeInterval *)tip forDate:(NSDate *)date

根据参数提供的时间点,返回所在日历单位的开始时间。如果startDate和interval均可以计算,则返回YES;否则返回NO

unit -- 日历单位

datep --

开始时间,通过参数返回

tip --

日历单位所对应的秒数,通过参数返回

date --

时间点参数

NSDate *dateOut = nil;

NSTimeInterval count =0;

NSDateComponents *compt = [[NSDateComponents alloc] init];

[compt setYear:2013];

[compt setMonth:3];

[compt setDay:22];

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [calendar dateFromComponents:compt];

BOOL b = [calendar rangeOfUnit:NSMonthCalendarUnit startDate:&dateOut interval:&count forDate:date];

if(b)

{

    //得到本地时间,避免时区问题

    NSTimeZone *zone = [NSTimeZone systemTimeZone];

    NSInteger interval = [zone secondsFromGMTForDate:dateOut];

    NSDate *localeDate = [dateOut dateByAddingTimeInterval:interval];


    NSLog(@"%@",localeDate);

    NSLog(@"%f",count);

}

else

{

    NSLog(@"无法计算");

}

上面的例子要求返回2013年3月22日当月的起始时间,以及当月的秒数。得到的结果是:2013-03-01 00:00:00 +0000,2678400。(2678400 = 31天* 24小时* 60分* 60秒)。

假如将上面的日历单位改为NSWeekCalendarUnit,那么得到的结果是:2013-03-17 00:00:00 +0000,604800。当周的第一天是3月17日。(604800 = 7天* 24小时* 60分* 60秒)。

假如将上面的日历单位改为NSYearCalendarUnit,那么得到的结果是:2013-01-01 00:00:00 +0000,31536000。这一年的第一天是1月1日,(31536000 = 365天* 24小时* 60分* 60秒)。

你可能感兴趣的:(NSDateComponents和NSCalendar释义)