iOS - OC NSCalendar 日曆

前言

@interface NSCalendar : NSObject <NSCopying, NSSecureCoding>
  • NSCalendar 對世界上現存的經常使用的歷法進行了封裝,既提供了不一樣曆法的時間信息,又支持日曆的計算。ide

    • NSCalendar -- 日曆類,它提供了大部分的日期計算接口,而且容許您在NSDate和NSDateComponents之間轉換
    • NSTimeZone -- 時區信息
    • NSLocale -- 本地化信息
    • NSDate -- 表示一個絕對的時間點
    • NSDateComponents -- 一個封裝了具體年月日、時秒分、周、季度等的類
    • NSDateFormatter -- 用來在日期和字符串之間轉換
  • 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 的做用確實是修改當前曆法中周的起始位置,可是不能修改週日對應的數值,只能修改一年或一個月中周的數量,以及周的次序。

一、日曆的建立

// 根據提供的日曆標示符初始化。
    /*
        identifier 的範圍能夠是:
            
            NSCalendarIdentifierGregorian         公曆
            NSCalendarIdentifierBuddhist          佛教日曆
            NSCalendarIdentifierChinese           中國農曆
            NSCalendarIdentifierHebrew            希伯來日曆
            NSCalendarIdentifierIslamic           伊斯蘭日曆
            NSCalendarIdentifierIslamicCivil      伊斯蘭教日曆
            NSCalendarIdentifierJapanese          日本日曆
            NSCalendarIdentifierRepublicOfChina   中華民國日曆(臺灣)
            NSCalendarIdentifierPersian           波斯歷
            NSCalendarIdentifierIndian            印度日曆
            NSCalendarIdentifierISO8601           ISO8601
    */
    NSCalendar *cal1 = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

    // 返回當前客戶端的邏輯日曆
    /*
        取得的值會一直保持在 cache 中,第一次用此方法實例化對象後,即便修改了系統日曆設定,這個對象也不會改變
    */
    NSCalendar *cal2 = [NSCalendar currentCalendar];
    
    // 返回當前客戶端的邏輯日曆
    /*
        當每次修改系統日曆設定,其實例化的對象也會隨之改變
    */
    NSCalendar *cal3 = [NSCalendar autoupdatingCurrentCalendar];

二、日曆的設置

NSCalendar *calendar = [NSCalendar currentCalendar];
    
    // 設置區域
    [calendar setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];
    
    // 設置時區
    /*
        設置時區,設置爲 GMT+8,即北京時間(+8)
    */
    [calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"CCT"]];
    [calendar setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:+28800]];
    
    // 設定每週的第一天從星期幾開始
    /*
        1 表明星期日開始,2 表明星期一開始,以此類推。默認值是 1
    */
    [calendar setFirstWeekday:2];
    
    // 設置每一年及每個月第一週必須包含的最少天數
    /*
        設定第一週最少包括 3 天,則 value 傳入 3
    */
    [calendar setMinimumDaysInFirstWeek:3];

三、日曆設置信息的獲取

NSCalendar *calendar = [NSCalendar currentCalendar];
    
    // 獲取日曆標示符
    /*
        有效的日曆標示符包括:
        
            gregorian
            buddhist
            chinese
            hebrew
            islamic
            islamic-civil
            japanese
            roc
            persian
            indian
            iso8601
    */
    NSString *calendarIdentifier =  calendar.calendarIdentifier;
    
    // 獲取地區信息
    /*
        語言地區
    */
    NSString *localeIdentifier = calendar.locale.localeIdentifier;
    NSString *localeIdentifier2 = [calendar.locale objectForKey:NSLocaleIdentifier];
        
    // 獲取時區信息
    NSTimeZone *timeZone = calendar.timeZone;
        
    // 獲取每週的第一天從星期幾開始
    /*
        缺省爲星期天
    */
    NSUInteger firstWeekday = calendar.firstWeekday;
        
    // 獲取第一週必須包含的最少天數
    /*
        缺省爲 1
    */
    NSUInteger minimumDaysInFirstWeek = calendar.minimumDaysInFirstWeek;

四、日曆信息的獲取

  • 1)獲取一個小的單位在一個大的單位裏面的序數code

    NSUInteger count = [calendar ordinalityOfUnit:NSCalendarUnitWeekday 
                                               inUnit:NSCalendarUnitWeekOfMonth 
                                              forDate:[NSDate date]];
    - (NSUInteger)ordinalityOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
    
        NSCalendarUnit包含的值有:
    
            NSCalendarUnitEra                 -- 紀元單位。對於 NSGregorianCalendar (公曆)來講,只有公元前(BC)和公元(AD);
                                                 而對於其它曆法可能有不少,例如日本和歷是以每一代君王統治來作計算。
            NSCalendarUnitYear                -- 年單位。值很大,至關於經歷了多少年,將來多少年。
            NSCalendarUnitMonth               -- 月單位。範圍爲1-12
            NSCalendarUnitDay                 -- 天單位。範圍爲1-31
            NSCalendarUnitHour                -- 小時單位。範圍爲0-24
            NSCalendarUnitMinute              -- 分鐘單位。範圍爲0-60
            NSCalendarUnitSecond              -- 秒單位。範圍爲0-60
            NSCalendarUnitWeekOfMonth / NSCalendarUnitWeekOfYear -- 周單位。範圍爲1-53
            NSCalendarUnitWeekday             -- 星期單位,每週的7天。範圍爲1-7
            NSCalendarUnitWeekdayOrdinal      -- 沒徹底搞清楚
            NSCalendarUnitQuarter             -- 幾刻鐘,也就是15分鐘。範圍爲1-4
            NSCalendarUnitWeekOfMonth         -- 月包含的週數。最多爲6個周
            NSCalendarUnitWeekOfYear          -- 年包含的週數。最多爲53個周
            NSCalendarUnitYearForWeekOfYear   -- 沒徹底搞清楚
            NSCalendarUnitTimeZone            -- 沒徹底搞清楚
    
        <1>、當小單位爲 NSCalendarUnitWeekday,大單位爲 NSCalendarUnitWeekOfMonth / NSCalendarUnitWeekOfYear 時
             (即某個日期在這一週是第幾天),根據 firstWeekday 屬性不一樣,返回的結果也不一樣。具體說明以下:
    
            當 firstWeekday 被指定爲星期天(即 = 1)時,它返回的值與星期幾對應的數值保持一致。好比:
                fromDate 傳入的參數是星期日,則函數返回 1
                fromDate 傳入的參數是星期一,則函數返回 2
            當 firstWeekday 被指定爲其它值時(即 <> 1)時,假設firstWeekday 被指定爲星期一(即 = 2),那麼:
                fromDate 傳入的參數是星期一,則函數返回 1
                fromDate 傳入的參數是星期二,則函數返回 2
                fromDate 傳入的參數是星期日,則函數返回 7
    
        <2>、當小單位爲 參數爲 NSCalendarUnitWeekOfMonth / NSCalendarUnitWeekOfYear,大單位爲 NSCalendarUnitYear 時
             (即某個日期在這一年中是第幾周),minimumDaysInFirstWeek 屬性影響它的返回值。具體說明以下:
    
                2005年1月
                日   一    二   三   四    五   六
                --------------------------------
                                              1
                2    3    4    5    6    7    8
                9    10   11   12   13   14   15
                16   17   18   19   20   21   22
                23   24   25   26   27   28   29
                30   31
    
                2005年1月第一週包括1號。
                a. 若是將 minimumDaysInFirstWeek 設定 = 1
                則 fromDate 傳入1月1號,方法均返回1  ==> 知足 minimumDaysInFirstWeek 指定的天數(最少1天),因此方法將其歸爲
                                                      2005年的第1周
                則 fromDate 傳入1月2-8號,方法均返回2
                則 fromDate 傳入1月9-15號,方法均返回3
                ......
    
                b. 若是將 minimumDaysInFirstWeek 設定爲 > 1,好比2
                則 fromDate 傳入1月1號,方法均返回53  ==> 不足2天,因此方法將其歸爲2004年的第53周
                則 fromDate 傳入1月2-8號,方法均返回1
                則 fromDate 傳入1月9-15號,方法均返回2
                ......
    
                2008年1月
                日   一    二   三   四    五   六
                ---------------------------------
                          1    2    3    4    5
                6    7    8    9    10   11   12
                13   14   15   16   17   18   19
                20   21   22   23   24   25   26
                27   28   29   30   31
    
                2005年1月第一週包括1-5號共5天。
                a. 若是將 minimumDaysInFirstWeek 設定爲 <= 5時
                則 fromDate 傳入1月1-5號,方法均返回1  ==> 知足 minimumDaysInFirstWeek 指定的天數,因此方法將其歸爲2008年的第1周
                則 fromDate 傳入1月6-12號,方法均返回2
                則 fromDate 傳入1月13-19號,方法均返回3
                ......
    
                b. 若是將 minimumDaysInFirstWeek 設定爲 > 5,好比6
                則 fromDate 傳入1月1-5號,方法均返回53  ==> 當週不足6天,因此方法將其歸爲2007年的第53周
                則 fromDate 傳入1月2-8號,方法均返回1
                則 fromDate 傳入1月9-15號,方法均返回2
                ......
    
        <3>、當小單位爲 參數爲 NSCalendarUnitWeekOfMonth / NSCalendarUnitWeekOfYear,大單位爲 NSCalendarUnitMonth 時
             (即某個日期在這一個月中是第幾周),minimumDaysInFirstWeek 屬性影響它的返回值。具體說明以下:
    
                2008年4月
                日   一    二   三   四    五   六
                ---------------------------------
                          1    2    3    4    5
                6    7    8    9    10   11   12
                13   14   15   16   17   18   19
                20   21   22   23   24   25   26
                27   28   29   30
    
                2008年4月第一週包括一、二、三、四、5號。
                a. 若是將 minimumDaysInFirstWeek 設定爲小於或等於5的數
                則 fromDate 傳入4月1-5號,方法均返回1
                則 fromDate 傳入4月6-12號,方法均返回2
                則 fromDate 傳入4月13-19號,方法均返回3
                ....
    
                b. 若是將 minimumDaysInFirstWeek 設定爲大於5的數
                則 fromDate 傳入1-5號,方法均返回0
                則 fromDate 傳入6-12號,方法均返回1
                則 fromDate 傳入13-19號,方法均返回2
                ....
  • 2)獲取一個小的單位在一個大的單位裏面的取值範圍orm

    NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:[NSDate date]];
        NSLog(@"%zi -- %zi", range.location, range.length);
    - (NSRange)rangeOfUnit:(NSCalendarUnit)smaller inUnit:(NSCalendarUnit)larger forDate:(NSDate *)date;
    
        調用這個方法要明確一點,取得的是"範圍"而不是"包含",下面是一些例子:
    
        <1>、小單位是 NSCalendarUnitDay,大單位是 NSCalendarUnitYear,並非要取這一年包含多少天,而是要取"天"(Day)這個單位
             在這一年(Year)的取值範圍。其實無論你提供的日期是多少,返回的值都是"1--31"。
    
        <2>、小單位是 NSCalendarUnitDay,大單位是 NSCalendarUnitMonth。要取得參數時間點所對應的月份下,"天"(Day)的取值範圍。
             根據參數時間的月份不一樣,值也不一樣。例如2月是1--2八、3月是 1--3一、4月是1--30。
    
        <3>、小單位是 NSCalendarUnitWeekOfMonth / NSCalendarUnitWeekOfYear,大單位是 NSCalendarUnitMonth。要取得參數
             時間點所對應的月份下,"周"(Week)的取值範圍。須要注意的是結果會受到 minimumDaysInFirstWeek 屬性的影響。在默認 
             minimumDaysInFirstWeek 狀況下,取得的範圍值通常是"1--5",從日曆上能夠看出來這個月包含5排,即5個周。
    
        <4>、小單位是 NSCalendarUnitDay,大單位是 NSCalendarUnitWeekOfMonth / NSCalendarUnitWeekOfYear。要取得周所包含
             的"天"(Day)的取值範圍。下面是一個示例日曆圖:
    
                2013年4月
                日   一    二   三   四    五   六
                ---------------------------------
                     1    2    3    4    5    6    
                7    8    9    10   11   12  13   
                14   15   16   17   18   19  20   
                21   22   23   24   25   26  27   
                28   29   30
    
                在上圖的日期條件下,假如提供的參數是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。
  • 3)獲取所在日曆單位的開始時間及所在日曆單位的總秒數對象

    NSDate *startDate = nil;
        NSTimeInterval intervalCount = 0;
    
        BOOL bl = [calendar rangeOfUnit:NSCalendarUnitMonth 
                              startDate:&startDate 
                               interval:&intervalCount 
                                forDate:[NSDate date]];
    
        if (bl) {
    
            // 獲得本地時間,避免時區問題
            startDate = [startDate dateByAddingTimeInterval:[[NSTimeZone systemTimeZone] secondsFromGMTForDate:startDate]];
    
            NSLog(@"%@",startDate);
            NSLog(@"%f",intervalCount);
        }
        else {
            NSLog(@"沒法計算");
        }
相關文章
相關標籤/搜索