NSCalendar + NSDateComponents
- 曆法能使人類確定每一日再無限的時間中的確切位置並記錄歷史。
- 日曆,曆法,一般曆法都是遵循固定的規則的,具有週期性。日曆都是已知的或可預測的。
- 任何一種具體的歷法,首先必須明確規定起始點,即開始計算的年代,這叫“紀元”;以及規定一年的開端,這叫“歲首”。此外,還要規定每年所含的日數,如何劃分月份,每月有多少天等等。
- NSCalendar對世界上現存的常用的歷法進行了封裝,既提供了不同曆法的時間信息,又支持日曆的計算。
- NSDateFomatter表示的時間默認以公曆(即陽曆)爲參考,可以通過設置calendar屬性變量獲得特定曆法下的時間表示。
- NSDate是獨立與任何曆法的,它只是時間相對於某個時間點的時間差;NSDate是進行日曆計算的基礎。
- NSDateComponents將時間表示成適合人類閱讀和使用的方式,通過NSDateComponents可以快速而簡單地獲取某個時間點對應的“年”,“月”,“日”,“時”,“分”,“秒”,“周”等信息。當然一旦涉及了年月日時分秒就要和某個曆法綁定,因此NSDateComponents必須和NSCalendar一起使用,默認爲公曆。
- NSDateComponents除了像上面說的表示一個時間點外,還可以表示時間段,例如:兩週,三個月,20年,7天,10分鐘,50秒等等。時間段用於日曆的計算,例如:獲取當前曆法下,三個月前的某個時間點。
- 可以說,要獲取某個時間點在某個曆法下的表示,需要NSDateComponents;要計算當前時間點在某個曆法下對應的一個時間段前或後的時間點,需要NSDateComponents。
- NSDateComponents返回的day, week, weekday, month, year這一類數據都是從1開始的。因爲日曆是給人看的,不是給計算機看的,從0開始就是個錯誤。
NSDateComponents實例化的方式
第一種:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//
先定義一個遵循某個曆法的日曆對象 NSCalendar
*greCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; //
通過已定義的日曆對象,獲取某個時間點的NSDateComponents表示,並設置需要表示哪些信息(NSYearCalendarUnit, NSMonthCalendarUnit, NSDayCalendarUnit等) NSDateComponents
*dateComponents = [greCalendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekCalendarUnit | NSWeekdayCalendarUnit | NSWeekOfMonthCalendarUnit | NSWeekOfYearCalendarUnit
fromDate:[NSDate date]]; NSLog(@ "year(年份):
%i" ,
dateComponents.year); NSLog(@ "quarter(季度):%i" ,
dateComponents.quarter); NSLog(@ "month(月份):%i" ,
dateComponents.month); NSLog(@ "day(日期):%i" ,
dateComponents.day); NSLog(@ "hour(小時):%i" ,
dateComponents.hour); NSLog(@ "minute(分鐘):%i" ,
dateComponents.minute); NSLog(@ "second(秒):%i" ,
dateComponents.second); //
Sunday:1, Monday:2, Tuesday:3, Wednesday:4, Friday:5, Saturday:6 NSLog(@ "weekday(星期):%i" ,
dateComponents.weekday); //
蘋果官方不推薦使用week NSLog(@ "week(該年第幾周):%i" ,
dateComponents.week); NSLog(@ "weekOfYear(該年第幾周):%i" ,
dateComponents.weekOfYear); NSLog(@ "weekOfMonth(該月第幾周):%i" ,
dateComponents.weekOfMonth); |
若獲取dateComponents對象時,設置components的時候未添加NSYearCalendarUnit,dateComponents.year將返回錯誤的數值,其他的也一樣,所以使用NSDateComponents表示時間時,要確保需要使用的數據都在componets中添加了。
第二種:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//
先定義一個遵循某個曆法的日曆對象 NSCalendar
*greCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; //
定義一個NSDateComponents對象,設置一個時間點 NSDateComponents
*dateComponentsForDate = [[NSDateComponents alloc] init]; [dateComponentsForDate
setDay:6]; [dateComponentsForDate
setMonth:5]; [dateComponentsForDate
setYear:2004]; //
根據設置的dateComponentsForDate獲取曆法中與之對應的時間點 //
這裏的時分秒會使用NSDateComponents中規定的默認數值,一般爲0或1。 NSDate
*dateFromDateComponentsForDate = [greCalendar dateFromComponents:dc]; //
定義一個NSDateComponents對象,設置一個時間段 NSDateComponents
*dateComponentsAsTimeQantum = [[NSDateComponents alloc] init]; [dateComponentsForDate
setDay:6]; //
在當前曆法下,獲取6天后的時間點 NSDate
*dateFromDateComponentsAsTimeQantum = [greCalendar dateByAddingComponents:dateComponentsAsTimeQantum toDate:[NSDate date] options:0]; |
第三種:
1
2
3
4
5
6
|
//
先定義一個遵循某個曆法的日曆對象 NSCalendar
*greCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; //
根據兩個時間點,定義NSDateComponents對象,從而獲取這兩個時間點的時差 NSDateComponents
*dateComponents = [greCalendar components:NSYearCalendarUnit fromDate:[NSDate dateWithTimeIntervalSince1970:0] toDate:[NSDate date] options:0]; NSLog(@ "number
of years:%i" ,
dateComponents.year); |
NSCalendar中比較重要的方法和概念
firstWeekday
firstWeekday是大家比較容易渾淆的東西。
大家在使用dateComponents.weekday獲取某天對應的星期時,會發現,星期日對應的值爲1,星期一對應的值爲2,星期二對應的值爲3,依次遞推,星期六對應的值爲7,這與我們平時理解的方式不一樣。然後,我們就開始找是不是可以設置這種對應關係。終於,我們在NSCalendar中發現了firstWeekday這個變量,從字面意思上看貌似就是我們尋找的那個東西。可是,設置過firstWeekday後,我們又發現完全沒有作用,真是鬱悶啊!其實,大家不必鬱悶,因爲鬱悶也沒用,iOS中規定的就是週日爲1,週一爲2,週二爲3,週三爲4,週四爲5,週五爲6,週六爲7,無法通過某個設置改變這個事實的,只能在使用的時候注意一下這個規則了。那firstWeekday是幹什麼用的呢?大家設置一下firstWeekday,再獲取一下dateComponents.weekOfYear或dateComponents.weekOfMonth,看看返回的數據是否發生了變化。firstWeekday的作用確實是修改當前曆法中周的起始位置,但是不能修改週日對應的數值,只能修改一年或一個月中周的數量,以及周的次序。
-(NSRange)rangeOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
答疑解惑:
-
Unit:單元
-
NSRange:
typedef struct _NSRange {
12NSUInteger location;
NSUInteger length;
} NSRange;
我們大致可以理解爲:某個時間點所在的“小單元”,在“大單元”中的數量(返回值range的location屬性變量的值一般是錯誤的)。例如:
1
2
3
4
|
//
當前時間對應的月份中有幾天 [[NSCalendar
currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]].length; //
當前時間對應的月份中有幾周(前面說到的firstWeekday會影響到這個結果) [[NSCalendar
currentCalendar] rangeOfUnit:NSWeekCalendarUnit inUnit:NSMonthCalendarUnit forDate:[NSDate date]].length; |
-(NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
我們大致可以理解爲:某個時間點所在的“小單元”,在“大單元”中的位置(從1開始)。例如:
1
2
3
4
5
6
7
|
//
當前時間對應的周是當前年中的第幾周 [[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]]; |
在這裏:NSWeekOfYearCalendarUnit, NSWeekOfMonthCalendarUnit與NSWeekCalendarUnit的使用結果相同,爲了避免渾淆,建議在此處使用NSWeekCalendar,而定義NSDateComponents時使用NSWeekOfYearCalendarUnit和NSWeekOfMonthCalendarUnit。
-(BOOL)rangeOfUnit:(NSCalendarUnit)unit startDate:(NSDate *)datep interval:(NSTimeInterval )tip forDate:(NSDate *)date;
我們大致可以理解爲:“某個時間點”所在的“單元”的起始時間,以及起始時間距離“某個時間點”的時差(單位秒)。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
NSDate
*startDateOfYear; NSDate
*startDateOfMonth; NSDate
*startDateOfWeek; NSDate
*startDateOfDay; NSTimeInterval
TIOfYear; NSTimeInterval
TIOfMonth; NSTimeInterval
TIOfWeek; NSTimeInterval
TIOfDay; [[NSCalendar
currentCalendar] rangeOfUnit:NSYearCalendarUnit startDate:&startDateOfYear interval:&TIOfYear forDate:[NSDate date]]; [[NSCalendar
currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startDateOfMonth interval:&TIOfMonth forDate:[NSDate date]]; [[NSCalendar
currentCalendar] rangeOfUnit:NSWeekCalendarUnit startDate:&startDateOfWeek interval:&TIOfWeek forDate:[NSDate date]]; [[NSCalendar
currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&startDateOfDay interval:&TIOfDay forDate:[NSDate date]]; NSLog(@ "firstDateOfYear:%@,
FirstDateOfMonth:%@, FirstDateOfWeek:%@, FirstDateOfDay:%@" ,
startDateOfYear, startDateOfMonth, startDateOfWeek, startDateOfDay); NSLog(@ "TIOfYear:%f,
TIOfMonth:%f, TIOfWeek:%f, TIOfDay:%f" ,
TIOfYear, TIOfMonth, TIOfWeek, TIOfDay); 常用方法:
NSDate *nowDate = [NSDate date]; NSLog(@"now date is: %@", nowDate);
NSCalendar *calendar = [NSCalendar currentCalendar]; NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekOfMonthCalendarUnit | NSWeekOfYearCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit; NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:nowDate];
NSInteger year = [dateComponent year]; NSInteger month = [dateComponent month]; NSInteger day = [dateComponent day]; NSInteger hour = [dateComponent hour]; NSInteger minute = [dateComponent minute]; NSInteger second = [dateComponent second];
NSInteger weekDay = [dateComponent weekday]; NSInteger weekDayOrdinal = [dateComponent weekdayOrdinal]; NSInteger weekOfMonth = [dateComponent weekOfMonth]; NSInteger weekOfYear = [dateComponent weekOfYear];
NSLog(@"year is: %ld", year); NSLog(@"month is: %ld", month); NSLog(@"day is: %ld", day); NSLog(@"hour is: %ld", hour); NSLog(@"minute is: %ld", minute); NSLog(@"second is: %ld", second); NSLog(@"weekDay is: %ld", weekDay); NSLog(@"weekDayOrdinal is: %ld", weekDayOrdinal); NSLog(@"weekDayOfMonth is: %ld", weekOfMonth); NSLog(@"weekDayOfYear is: %ld", weekOfYear);
|