IOS時間與日期處理

主要有以下類: 

NSDate -- 表示一個絕對的時間點
NSTimeZone -- 時區信息
NSLocale -- 本地化信息
NSDateComponents -- 一個封裝了具體年月日、時秒分、周、季度等的類
NSCalendar -- 日曆類,它提供了大部分的日期計算接口,並且允許您在NSDate和NSDateComponents之間轉換
NSDateFormatter -- 用來在日期和字符串之間轉換

NSDate

NSDate用來表示公曆的GMT時間(格林威治時間)。 有下面幾種初始化方法:

1. - (id)init

默認初始化,返回當前時間,也可以直接調用類方法 +(id)date

NSDate *date = [[NSDate alloc] init];
//NSDate *date = [NSDate date];
NSLog(@"print date is %@",date);

將打印出計算機當前時間:2013-03-04 08:57:20 +0000

2. - (id)initWithTimeIntervalSinceNow:(NSTimeInterval)seconds

以當前時間的偏移秒數來初始化,也可以直接調用類方法 + (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)seconds

NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:20];
//NSDate *date = [NSDate dateWithTimeIntervalSinceNow:20];
NSLog(@"print date is %@",date);

假如當前時間是2013-03-04 08:57:20 +0000,那麼初始化後得到的時間是2013-03-04 08:57:40 +0000

3. - (id)initWithTimeIntervalSince1970:(NSTimeInterval)seconds

以GMT時間的偏移秒數來初始化,也可以直接調用類方法 + (id)dateWithTimeIntervalSince1970:(NSTimeInterval)seconds

NSDate *date = [[NSDate alloc] initWithTimeIntervalSince1970:-20];
//NSDate *date = [NSDate dateWithTimeIntervalSince1970:-20];
NSLog(@"print date is %@",date);

得到的時間是格林威治時間往前20秒,將打印出:1969-12-31 23:59:40 +0000

4. - (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds

以2001-1-1 0:0:0的偏移秒數來初始化,也可以直接調用類方法 + (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds

NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:80];
//NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:80];
NSLog(@"print date is %@",date);

將打印出:2001-01-01 00:01:20 +0000

5. - (id)initWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)refDate

以基準時間的偏移秒數來初始化,也可以直接調用類方法 + (id)dateWithTimeInterval:(NSTimeInterval)seconds sinceDate:(NSDate *)date

NSDate *date1 = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:20];
NSLog(@"print date1 is %@",date1);
    
NSDate *date2 = [[NSDate alloc] initWithTimeInterval:10 sinceDate:date1];
//NSDate *date2 = [NSDate dateWithTimeInterval:10 sinceDate:date1];
NSLog(@"print date2 is %@",date2);

第一個基準時間是2001-01-01 00:00:20 +0000,根據基準時間偏移10秒的結果是2001-01-01 00:00:30 +0000

6.  + (id)distantPast 與 + (id)distantFuture

這兩個是類方法,分別用來返回一個極早的時間點和一個極晚的時間點

NSDate *date = [NSDate distantFuture];
NSLog(@"future date is %@",date);

NSDate *date2 = [NSDate distantPast];
NSLog(@"past date is %@",date2);

distantPast將返回:0001-12-30 00:00:00 +0000,distantFuture將返回:4001-01-01 00:00:00 +0000

NSDate的常用對象方法:

1. -(id)dateByAddingTimeInterval:(NSTimeInterval)seconds

返回以當前NSDate對象爲基準,偏移多少秒後得到的新NSDate對象。(舊方法 - (id)addTimeInterval:(NSTimeInterval)seconds已被棄用)

NSDate *date = [NSDate dateWithTimeIntervalSince1970:0];
NSDate *date2 = [date dateByAddingTimeInterval:-20];
NSLog(@"%@",date2);

2. - (BOOL)isEqualToDate:(NSDate *)anotherDate

將當前對象與參數傳遞的對象進行比較,根據是否相同返回BOOL值

NSDate *date = [NSDate dateWithTimeIntervalSince1970:0];
NSDate *date2 = [NSDate dateWithTimeInterval:0 sinceDate:date];
BOOL isEqual = [date isEqualToDate:date2];
NSLog(@"%i",isEqual);

3. - (NSDate *)earlierDate:(NSDate *)anotherDate 與 - (NSDate *)laterDate:(NSDate *)anotherDate

比較兩個NSDate對象,返回較早/較晚的時間點,並以新NSDate對象的形式返回

NSDate *date = [NSDate dateWithTimeIntervalSince1970:0];
NSDate *date2 = [NSDate dateWithTimeInterval:-50 sinceDate:date];

NSDate *date3 = [date earlierDate:date2];
NSLog(@"earlier date is %@",date3);

NSDate *date4 = [date laterDate:date2];
NSLog(@"later date is %@",date4);

4. - (NSComparisonResult)compare:(NSDate *)anotherDate

將當前對象與參數傳遞的對象進行比較,如果相同,返回0(NSOrderedSame);對象時間早於參數時間,返回-1(NSOrderedAscending);對象時間晚於參數時間,返回1(NSOrderedDescending)

NSDate *date = [NSDate dateWithTimeIntervalSince1970:0];
NSDate *date2 = [NSDate dateWithTimeInterval:-50 sinceDate:date];

NSInteger result = [date compare:date2];
NSLog(@"%i",result);

5. - (NSTimeInterval)timeIntervalSince1970

返回當前對象時間與1970-1-1 0:0:0的相隔秒數,也可以這樣理解:從1970-1-1 0:0:0開始,經過多少秒到達對象指定時間

NSDate *date = [NSDate dateWithTimeIntervalSince1970:50];
NSInteger seconds = [date timeIntervalSince1970];
NSLog(@"%i",seconds);

將返回結果50

6. - (NSTimeInterval)timeIntervalSinceReferenceDate

返回當前對象時間與2001-1-1 0:0:0的相隔秒數,也可以這樣理解:從2001-1-1 0:0:0開始,經過多少秒到達對象指定時間

NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:-30];
NSInteger seconds = [date timeIntervalSinceReferenceDate];
NSLog(@"%i",seconds);

將返回結果-30,負數代表從2001-1-1 0:0:0開始,倒退30秒到達當前時間。

7. - (NSTimeInterval)timeIntervalSinceNow

返回當前對象時間與客戶端時間的相隔秒數,也可以這樣理解:從客戶端當前時間開始,經過多少秒到達對象指定時間。

NSDate *date = [NSDate dateWithTimeIntervalSinceNow:100];
NSInteger seconds = [date timeIntervalSinceNow];
NSLog(@"%i",seconds);

經測試返回了結果99,但初始化時提供的參數是100。這可能是因爲第一句初始化代碼到第二句計算代碼之間有個1秒內的延時,所以計算時的客戶端時間比初始化時的客戶端時間快了1秒。

8. - (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate

返回當前對象時間與參數傳遞的對象時間的相隔秒數,也可以這樣理解:從參數時間開始,經過多少秒到達對象執行時間。

NSDate *date = [NSDate dateWithTimeIntervalSince1970:0];
NSDate *date2 = [NSDate dateWithTimeInterval:50 sinceDate:date];
NSInteger seconds = [date timeIntervalSinceDate:date2];
NSLog(@"%i",seconds);

將返回結果-50,date爲1970-1-1 0:0:0,date2爲1970-1-1 0:0:50,從date2的時間開始,倒退50秒到達date的時間。

NSTimeZone

NSTimeZone表示時區信息。 有下面幾種初始化方法:

1. + (id)timeZoneWithName:(NSString *)aTimeZoneName / - (id)initWithName:(NSString *)aName

根據時區名稱初始化。可以調用NSTimeZone的類方法 + (NSArray *)knownTimeZoneNames來返回所有已知的時區名稱。

NSTimeZone *zone = [[NSTimeZone alloc] initWithName:@"America/Chicago"];
//NSTimeZone *zone = [NSTimeZone timeZoneWithName:@"America/Chicago"];
NSLog(@"%@",zone);

打印出:America/Chicago (CST) offset -21600

2. + (id)timeZoneWithAbbreviation:(NSString *)abbreviation

根據時區縮寫初始化。例如:EST(美國東部標準時間)、HKT(香港標準時間)

NSTimeZone *zone = [NSTimeZone timeZoneWithAbbreviation:@"EST"];
NSLog(@"%@",zone);

打印出:Asia/Hong_Kong (HKT) offset 28800

3. + (NSTimeZone *)systemTimeZone

返回系統時區

NSTimeZone *zone = [NSTimeZone systemTimeZone];
NSLog(@"%@",zone);

假如時區是上海,打印出的時區信息將會是:Asia/Shanghai (CST (China)) offset 28800,28800代表相對於GMT時間偏移的秒數,即8個小時。(8*60*60)

4. + (NSTimeZone *)localTimeZone

返回本地時區,與systemTimeZone的區別在於:本地時區可以被修改,而系統時區不能修改。


NSTimeZone *systemZone = [NSTimeZone systemTimeZone];
NSTimeZone *localZone = [NSTimeZone localTimeZone];

NSLog(@"%@",systemZone);
NSLog(@"%@",localZone);

打印出的系統時區仍然是:Asia/Shanghai (CST (China)) offset 28800;而本地時區經過修改後,變成了:Local Time Zone (America/Chicago (CST) offset -21600)

5. + (id)timeZoneForSecondsFromGMT:(NSInteger)seconds

根據零時區的秒數偏移返回一個新時區對象

NSTimeZone *zone = [NSTimeZone timeZoneForSecondsFromGMT:28800];
NSLog(@"%@",zone);

打印出:GMT+0800 (GMT+08:00) offset 28800

NSTimeZone常用對象方法與類方法:

1. + (NSArray *)knownTimeZoneNames

以數組的形式返回所有已知的時區名稱

NSArray *zoneArray = [NSTimeZone knownTimeZoneNames];
for(NSString *str in zoneArray)
{
    NSLog(@"%@",str);
}

2. - (NSString *)name / - (NSString *)abbreviation

返回時區對象的名稱或縮寫

NSTimeZone *zone = [NSTimeZone localTimeZone];
NSString *strZoneName = [zone name];
NSString *strZoneAbbreviation = [zone abbreviation];
NSLog(@"name is %@",strZoneName);
NSLog(@"abbreviation is %@",strZoneAbbreviation);

name is Asia/Hong_Kong

abbreviation is HKT

3. - (NSInteger)secondsFromGMT

得到當前時區與零時區的間隔秒數

NSTimeZone *zone = [NSTimeZone localTimeZone];
int seconds = [zone secondsFromGMT];
NSLog(@"%i",seconds);

NSLoale

NSLoale類返回本地化信息,主要體現在"語言"和"區域格式"這兩個設置項。有下面幾種初始化方法:

1. + (id)systemLocale

返回系統初始本地化信息

NSLocale *locale = [NSLocale systemLocale];
NSLog(@"%@",[[locale objectForKey:NSLocaleCalendar] calendarIdentifier]);

2. + (id)currentLocale / + (id)autoupdatingCurrentLocale

這兩個類方法都將返回當前客戶端的本地化信息,區別在於:currentLocale取得的值會一直保持在cache中,第一次用此方法實例化對象後,即使修改了本地化設定,這個對象也不會改變。而使用autoupdatingCurrentLocale,當每次修改本地化設定,其實例化的對象也會隨之改變。

下面的代碼演示了區別所在,假設初始本地化信息爲en_US,先用這兩個函數分別初始化兩個對象,然後修改本地化設定語言爲臺灣繁體中文,再重新打印這兩個對象的信息:

NSLocale *locale1;
NSLocale *locale2;

- (IBAction)doTest:(id)sender 
{
    locale1 = [NSLocale currentLocale];
    locale2 = [NSLocale autoupdatingCurrentLocale];

    NSLog(@"%@",locale1.localeIdentifier); //print "en_US"
    NSLog(@"%@",locale2.localeIdentifier); //print "en_US"
}

- (IBAction)doAgain:(id)sender 
{
    NSLog(@"%@",locale1.localeIdentifier); //print "en_US"
    NSLog(@"%@",locale2.localeIdentifier); //print "zh_TW"
}

3. - (id)initWithLocaleIdentifier:(NSString *)string

用標示符初始化本地化信息

NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
NSString *strSymbol = [locale objectForKey:NSLocaleCurrencySymbol];
NSLog(@"%@",strSymbol);

代碼用"zh_CN"來初始化對象,然後再打印出對象的貨幣符號,得到的結果是人民幣符號¥

NSLoale常用對象方法與類方法:

1. - (id)objectForKey:(id)key

根據不同的key返回各種本地化信息,例如下面的代碼返回了當前貨幣符號:

NSLocale *locale = [NSLocale currentLocale];
NSString *strSymbol = [locale objectForKey:NSLocaleCurrencySymbol];
NSCalendar *calendar = [[NSLocale currentLocale] objectForKey:NSLocaleCalendar];

2. - (NSString *)displayNameForKey:(id)key value:(id)value

顯示特定地區代號下相應鍵的顯示名稱:

NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
NSString *str = [locale displayNameForKey:NSLocaleIdentifier value:@"en_US"];
NSLog(@"%@",str);

第一句代碼代表以中文來實例化對象,然後得到"en_US"的NSLocaleIdentifier鍵的顯示名稱。最後輸出的結果是"英文(美國)"

NSDateComponents

NSDateComponents封裝了具體年月日、時秒分、周、季度等

[compt setEra:1];
[compt setYear:2013];
[compt setMonth:3];
[compt setDay:15];
[compt setHour:11];
[compt setMinute:20];
[compt setSecond:55];
[compt setQuarter:2];
[compt setTimeZone:[NSTimeZone systemTimeZone]];
[compt setWeek:3];
[compt setWeekday:4];
[compt setWeekOfMonth:3];
[compt setWeekOfYear:2];
[compt setCalendar:[NSCalendar currentCalendar]];

NSDateComponents相關方法:

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

取得一個NSDate對象的1個或多個部分,用NSDateComponents來封裝

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來封裝

NSDate *date = [NSDate date];
NSDate *date2 = [NSDate dateWithTimeInterval:5*60*60+75 sinceDate: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對象

[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類型的時間增量

[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 *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

如圖所示,如果從星期天開始,日曆的表現形式:

  IOS時間與日期處理


 如果從星期二開始,日曆的表現形式:

IOS時間與日期處理

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];
int count = [calendar ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:date];
NSLog(@"%d",count);

默認firstWeekday爲1(星期天開始)的情況下,得到的結果是2,從下圖可以看到是第2天。

IOS時間與日期處理

假如firstWeekday被設置爲2(星期一開始)的情況下,得到的結果是1,從下圖可以看到是第1天

IOS時間與日期處理

② 當小單位爲NSWeekCalendarUnit,大單位爲NSYearCalendarUnit時(即某個日期在這一年中是第幾周),根據minimumDaysInFirstWeek屬性不同,返回的結果也不同。

IOS時間與日期處理

[compt setYear:2013];
[compt setMonth:1];
[compt setDay:20];

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDate *date = [calendar dateFromComponents:compt];

//[calendar setMinimumDaysInFirstWeek:6];
int count = [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

根據參數提供的時間點,得到一個小的單位在一個大的單位裏面的取值範圍

[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)的取值範圍。下面是一個示例日曆圖:

IOS時間與日期處理

在上圖的日期條件下,假如提供的參數是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 -- 時間點參數

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秒)。

NSDateFormatter

NSDateFormatter的日期格式如下:

一般會顯示公元前(BC)和公元(AD)

y -- 年
假如是2013年,那麼yyyy=2013,yy=13  

M -- 月
假如是3月,那麼M=3,MM=03,MMM=Mar,MMMM=March
假如是11月,那麼M=11,MM=11,MMM=Nov,MMMM=November

w -- 年包含的周
假如是1月8日,那麼w=2(這一年的第二個周)

W -- 月份包含的周(與日曆排列有關)
假如是2013年4月21日,那麼W=4(這個月的第四個周)

F -- 月份包含的周(與日曆排列無關)
和上面的W不一樣,F只是單純以7天爲一個單位來統計周,例如7號一定是第一個周,15號一定是第三個周,與日曆排列無關。

D -- 年包含的天數
假如是1月20日,那麼D=20(這一年的第20天)
假如是2月25日,那麼D=31+25=56(這一年的第56天)

d -- 月份包含的天數
假如是5號,那麼d=5,dd=05
假如是15號,那麼d=15,dd=15

E -- 星期 
假如是星期五,那麼E=Fri,EEEE=Friday

a -- 上午(AM)/下午(PM)

H -- 24小時制,顯示爲0--23
假如是午夜00:40,那麼H=0:40,HH=00:40

h -- 12小時制,顯示爲1--12
假如是午夜00:40,那麼h=12:40

K -- 12小時制,顯示爲0--11
假如是午夜00:40,那麼K=0:40,KK=00:40

k -- 24小時制,顯示爲1--24
假如是午夜00:40,那麼k=24:40

m -- 分鐘
假如是5分鐘,那麼m=5,mm=05
假如是45分鐘,那麼m=45,mm=45

s -- 秒
假如是5秒鐘,那麼s=5,ss=05
假如是45秒鐘,那麼s=45,ss=45

S -- 毫秒
一般用SSS來顯示

z -- 時區
表現形式爲GMT+08:00
 
Z -- 時區
表現形式爲+0800

NSDateFormatter的兩個最實用的方法是dateFromString和stringFromDate,前者將一個字符串經過格式化後變成NSDate對象,後者將NSDate對象格式化成字符串。

在調用setDateFormat設置格式化字符串時,可以加入一些別的字符串,用單引號來引入,例如:

[formatter setDateFormat:@"yyyy-MM-dd 'some ''special'' string' HH:mm:ss"];

使用NSDateFormatter轉換時間字符串時,默認的時區是系統時區,例如在中國一般都是北京時間(+8),如果直接轉換會導致結果相差8小時,所以一般的做法是先指定時區爲GMT標準時間再轉換,例如:

[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss z"];

NSDateComponents *compt = [[NSDateComponents alloc] init];
[compt setYear:2013];
[compt setMonth:3];
[compt setDay:13];
[compt setHour:1];
[compt setMinute:55];
[compt setSecond:28];

NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *date = [calendar dateFromComponents:compt];
NSLog(@"%@",date);
NSString *str = [formatter stringFromDate:date];
NSLog(@"%@",str);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章