相關(guān)資源
NSDate 秒紧、NSTimeZone 幻工、NSCalendar 和 NSDateFormatter
NSDate 、NSTimeZone 效五、NSCalendar和NSDateFormatter這四個類或者說對象都是相互獨立的地消,他們之間有一定的關(guān)系,一定要認清畏妖。
- NSDate
// 獲取現(xiàn)在時間脉执,這個時間是現(xiàn)在的格林威治標準時間,和時區(qū)戒劫、語言都沒有關(guān)系
[NSDate date];
- NSTimeZone
@property (class, readonly, copy) NSTimeZone *systemTimeZone;
@property (class, copy) NSTimeZone *defaultTimeZone;
@property (class, readonly, copy) NSTimeZone *localTimeZone
說明
- defaultTimeZone設置之前半夷,和systemTimeZone共享一個timeZone對象
- defaultTimeZone設置之后,會影響NSDateFormatter和NSCalendar的默認時區(qū)(除非單獨設置)迅细。當你獲取defaultTimeZone之后巫橄,獲取的zone就是一個獨立的對象了,即使你重新setDefaultTimeZone:也不會影響它茵典。
- localTimeZone更像是一個單例對象(程序范圍內(nèi))湘换,這個實例變量值會跟隨defaultTimeZone的設置而變化。
-
NSDateFormatter
// 時間戳轉(zhuǎn)換成時間的方法(返回字符串)
- (NSString *)timeStrWithInterval:(NSString *)interval {
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[interval doubleValue]/1000.0];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeZone = [NSTimeZone timeZoneWithName:@"Asia/Shanghai"];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *timeString = [formatter stringFromDate:date];
return timeString;
}
> 這里可以看到date格式化會受到時區(qū)影響统阿,反向格式化也一樣彩倚。
4. NSCalendar
> 1. 日歷,歷法扶平,一般歷法都是遵循固定的規(guī)則的帆离,具有周期性。日歷都是已知的或可預測的结澄。
> 2. NSDate是獨立與任何歷法的哥谷,它只是時間相對于某個時間點的時間差岸夯;NSDate是進行日歷計算的基礎。
> 3. 下面的兩個例子(在**獲取日歷一周索引值**標題下)们妥,已經(jīng)清晰反映了TimeZone和日歷的關(guān)系猜扮。
> 通過[[NSCalendar currentCalendar] setTimeZone:[NSTimeZone localTimeZone]]對日歷設置時區(qū);
**其他重要API**
// 當前時間對應的星期幾(索引)
[[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:[NSDate date]];
// 當前時間對應的周是當前月中的第幾周
[[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitWeekOfMonth inUnit:NSCalendarUnitYear forDate:[NSDate date]];
[[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitWeekOfMonth inUnit:NSCalendarUnitMonth forDate:[NSDate date]];
// 當前時間對應的周是當前年中的第幾周
[[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitWeekOfYear inUnit:NSCalendarUnitYear forDate:[NSDate date]];
#### 獲取日歷一周索引值
NSCalendar *calendar = [NSCalendar currentCalendar]; //
NSLog(@"FirstWeekday = %ld",calendar.firstWeekday);//默認值 是 1。
[calendar setFirstWeekday:1]; // 設定日歷每周的第一天從星期幾開始王悍,比如:如需設定從星期日開始(“開始”意味著日歷的第一天(索引為1)對應的是星期天)破镰,則value傳入1 ,如需設定從星期一開始压储,則value傳入2 鲜漩,以此類推。
// 這里到天day和hour
NSDateComponents *comp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour fromDate:date];
NSLog(@"date = %@",date); // 2017-05-18 11:27:37 +0000
NSLog(@"dayComponet = %ld",comp.day);// 打印結(jié)果是18
NSLog(@"HourComponet = %ld",comp.hour);// 14H
// 從打印結(jié)果可以看出集惋,calendar先把date加了3個小時孕似,再處理component
// newDate
NSDate *newDate = [calendar dateFromComponents:comp];
NSLog(@"newDate = %@", newDate);// 2017-05-18 11:00:00 +0000 ,也就是說從calendar取出來的date是受NSTimeZone限制的。
// 從打印結(jié)果分析刮刑,calendar先components取出數(shù)值喉祭,再減去3小時。
// 設置為這個月的第一天
[comp setDay:1]; // 把comp的day屬性設置為一號雷绢,即comp是5月1號14H
NSLog(@"dateComponet = %ld",comp.day);// 打印結(jié)果是1
NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp];
NSLog(@"firstDayOfMonthDate = %@",firstDayOfMonthDate);// 2017-05-01 11:00:00 +0000
NSDateFormatter *fommatter = [[NSDateFormatter alloc] init];
[fommatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *timeString = [fommatter stringFromDate:firstDayOfMonthDate];
NSLog(@"timeStr = %@",timeString);// 2017-05-01 14:00:00,這里可以看出fommatter也受時區(qū)影響泛烙。
// 經(jīng)測試firstDayOfMonthDate 取值在2017-04-40 21:00:00 +0000 ~ 2017-05-01 21:00:00 +0000(不包括)之間,下面方法返回結(jié)果都一樣翘紊,所以Calendar 受TimeZone影響蔽氨,會給date自動加3小時。
NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; // 這個月第一天在當前日歷的順序
// 返回某個特定時間(date)其對應的小的時間單元(smaller)在大的時間單元(larger)中的順序位置(索引值)
// 如果這里值是2帆疟,因為前面設置的周日是第一位置鹉究,所以這里的索引2,對應的應該是周一踪宠。
NSLog(@"firstWeekday = %ld",firstWeekday);
> 本次代碼分析的是component保留hour的情況自赔,下面gif圖是本人在第二天的運行的截圖,上面代碼分析是在18號柳琢。
> ![Calendar1.gif](http://upload-images.jianshu.io/upload_images/3448645-af67f4a9d587bd54.gif?imageMogr2/auto-orient/strip)
NSCalendar *calendar = [NSCalendar currentCalendar];
NSLog(@"FirstWeekday = %ld",calendar.firstWeekday);//默認值 是 1绍妨。
[calendar setFirstWeekday:2];
NSLog(@"date = %@",date); // 如果是5月31號21:00到6.1號21點(不包括)
// 這里只到天day
NSDateComponents *comp = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
NSLog(@"dateComponet = %ld",comp.day);// 打印結(jié)果是1,component 是6.1
// newDate
NSDate *newDate = [calendar dateFromComponents:comp];
NSLog(@"newDate = %@",newDate);// 這里的結(jié)果會是5月31號 21:00:00 +0000
// 設置為這個月的第一天
[comp setDay:1]; // 把comp的day屬性設置為一號染厅,即comp是6月1號
NSLog(@"dateComponet = %ld",comp.day);// 打印結(jié)果是1
NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp];
NSLog(@"date = %@",firstDayOfMonthDate);// 05-31 21:00:00 +0000
// 經(jīng)測試firstDayOfMonthDate 取值在2017-04-40 21:00:00 +0000 ~ 2017-05-01 21:00:00 +0000(不包括)之間痘绎,下面方法返回結(jié)果都一樣。date會加3個小時肖粮,變成6月份的日歷。
NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; // 這個月第一天在當前日歷的順序
// 返回某個特定時間(date)其對應的小的時間單元(smaller)在大的時間單元(larger)中的順序位置(索引值)
// 這里值是1尔苦,因為前面設置的周一是第一位置涩馆,所以這里的索引1行施,對應的就是周一。
NSLog(@"firstWeekday = %ld",firstWeekday);
> 本次代碼分析的是component只保留到day的情況 魂那。下面gif圖是本人在第二天的運行的截圖蛾号,上面代碼分析是在18號。
> ![Calendar.gif](http://upload-images.jianshu.io/upload_images/3448645-e90a6a4e3710ebb9.gif?imageMogr2/auto-orient/strip)
> 上面兩個例子都沒有問題涯雅,關(guān)鍵是
>
> 1. 涉及到TimeZone鲜结,對TimeZone對象的分析很關(guān)鍵。[NSTimeZone setDefaultTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Vilnius"]]的設置沒在上面代碼中顯示活逆,這是歐洲東時區(qū)三區(qū)的一個設置精刷,也可以通過單獨設置日歷的時區(qū)對象屬性。
> 2. 第二個關(guān)鍵部分是:找到對應月份和當前月對應的第一天蔗候,只要確保月份沒有找錯(component對應的月份就是最關(guān)鍵的月份)怒允,邏輯上就是對的。 如果date(格林威治標準時間GMT([NSDate date]))是5月31號21:00锈遥,component對應的數(shù)字就是6(month)和1(day)纫事,日歷內(nèi)部對應的“日期”就是6月1號00:00(以東三時區(qū)為例);component設置第一天對應的相關(guān)數(shù)值也是6(month)和1(day)所灸,然后用日歷轉(zhuǎn)化為date就是5月31號21:00丽惶,日歷內(nèi)部對應的“日期”就是6月1號00:00。
> 3. 第三個關(guān)鍵部分是:找到第一個“日期”對應的星期數(shù)爬立,用的時間(NSDate)可能是上個月的時間钾唬,比如:date(格林威治標準時間GMT([NSDate date]))是5月31號21:00,然而時間對應“日期”(6月1號00:00)才是日歷要查詢的依據(jù)(日歷會根據(jù)TimeZone自動調(diào)整date成“日期”)懦尝。
**找到日期對應月的第一天日期(更直接的方法)**
> 下面方法更直接知纷,但是通過上面的代碼,我們可以更好地分析本月第一天會是上個月的日期的情況陵霉。
- (NSDate *)firstDayOfCurrentMonthForDate:(NSDate *)date {
NSDate *startDate = nil;
BOOL ok = [[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startDate interval:NULL forDate:date];
return startDate;
}