iOS日期相關(guān)的NSDate,NSCalendar,NSDateComponents,NSDateFormatter詳解

NSDate對象封裝單個時間點鸳兽,與之相關(guān)的幾個類分別是: NSCalendar, NSDateComponents, NSDateComponentsFormatter
日期時間編程指南

一掂铐、NSDate 只能單純的獲取到某個時間點

1.獲取當(dāng)前時間點:

NSDate *date = [NSDate date];
NSDate *date1 = [[NSDate alloc]init];

2.按時間間隔創(chuàng)建日期
- (instancetype)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)ti

NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate *tomorrow = [[NSDate alloc] initWithTimeIntervalSinceNow:secondsPerDay];
NSDate *yesterday = [[NSDate alloc] initWithTimeIntervalSinceNow:-secondsPerDay];

3.通過添加時間間隔來創(chuàng)建日期

NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate *today = [[NSDate alloc] init];
NSDate *tomorrow, *yesterday;
   
tomorrow = [today dateByAddingTimeInterval:secondsPerDay];
yesterday = [today dateByAddingTimeInterval:-secondsPerDay];

4.日期之間的精確比較,
這三個方法都是精確到亞秒級別的

-(NSDate *)earlierDate:(NSDate *)anotherDate;//返回較早的那個日期
-(NSDate *)laterDate:(NSDate *)anotherDate;//返回較晚的那個時期
-(BOOL)isEqualToDate:(NSDate *)otherDate;//比較兩個日期是不是想等

[tomorrow isEqualToDate:NSDate.date];

如果在某個能接受的范圍內(nèi)就相等(1分鐘內(nèi)都算相等)

-(NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate;這個方法用來計算當(dāng)前日期和另一個日期之間的時間差

 if(fabs([date2 timeIntervalSinceDate:date1])<60){
        //…
}

二、NSCalendar 日歷對象封裝有關(guān)計算時間的系統(tǒng)的信息贸铜,其中定義了年的開始堡纬,長度和分度。您可以使用日歷對象在絕對時間和日期成分(例如年蒿秦,天或分鐘)之間進行轉(zhuǎn)換烤镐。

1.創(chuàng)建日歷了
用戶首選語言環(huán)境的日歷

NSCalendar *calender = [NSCalendar currentCalendar];

創(chuàng)建由給定標(biāo)識符指定的新日歷。

+(nullable NSCalendar *)calendarWithIdentifier:(NSCalendarIdentifier)calendarIdentifierConstant

標(biāo)識由系統(tǒng)指定,隨便看幾個常用的:
NSCalendarIdentifierGregorian 陽歷
NSCalendarIdentifierBuddhist 佛教日歷
NSCalendarIdentifierChinese 中國日歷,農(nóng)歷
......

NSCalendar *calender = [NSCalendar calendarWithIdentifier: NSCalendarIdentifierGregorian];

用戶創(chuàng)建日歷,和currentCalender是一樣的

NSCalendar * usersCalendar = [[NSLocale currentLocale] objectForKey:NSLocaleCalendar];

2.相關(guān)屬性,會影響到后面的計算結(jié)果

@property (nullable, copy) NSLocale *locale;地區(qū)

例如:en_US

@property (copy) NSTimeZone *timeZone;時區(qū)

例如:Asia/Shanghai (GMT+8) offset 28800

@property NSUInteger firstWeekday;每周星期幾作為第一天,默認星期天是第一天

設(shè)置星期一是第一天:firstWeekday = 2;

@property NSUInteger minimumDaysInFirstWeek;每周最少有幾天,低于這個數(shù)的不算做一周

比如:
image.png

5月的第一天是星期五,第一周只有2天,如果設(shè)置minimumDaysInFirstWeek為3,那么通過這個方法計算,5月1日是這個月的第0周,5月3號屬于第一周,5月31屬于第5周

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

//指定日期 2020-5-1 14:00:00
 NSDateComponents *components = [[NSDateComponents alloc]init];
 components.year = 2020;
 components.month = 5;
 components.day =30;
 components.hour = 14;
 NSDate *date = [[NSCalendar currentCalendar] dateFromComponents:components];
 NSCalendar *calender = NSCalendar.currentCalendar;
//設(shè)置每周的最小天數(shù) 3
 calender.minimumDaysInFirstWeek = 3;
NSInteger nums =  [calender ordinalityOfUnit:NSCalendarUnitWeekOfMonth inUnit:NSCalendarUnitMonth forDate:date];

系統(tǒng)提供的日歷單位:常用的如下

NSCalendarUnitYear 年
NSCalendarUnitMonth 月 1-12
NSCalendarUnitDay 天 1-31
NSCalendarUnitHour 小時 0-24
NSCalendarUnitMinute 分鐘0-60
NSCalendarUnitSecond 秒 0-60
NSCalendarUnitWeekday 星期 1-7
NSCalendarUnitQuarter 季度 1-4
NSCalendarUnitWeekOfMonth 一個月多少周 最多6
NSCalendarUnitWeekOfYear 一年最多周53

3.接下來說一些常規(guī)操作,有些需要結(jié)合NSDateComponents類使用
3.1當(dāng)前日歷單位的最小,最大長度

-(NSRange)minimumRangeOfUnit:(NSCalendarUnit)unit;
-(NSRange)maximumRangeOfUnit:(NSCalendarUnit)unit;

例如:每月最大最小有多少天?

[calender minimumRangeOfUnit:NSCalendarUnitDay].length //28
[calender maximumRangeOfUnit:NSCalendarUnitDay].length//31

3.2.根據(jù)當(dāng)前時間點,計算指定單位的長度,比如:當(dāng)前時間所屬的月(5月)的長度是31天

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

[NSCalendar.currentCalendar
                          rangeOfUnit:NSCalendarUnitMonth
                          inUnit:NSCalendarUnitYear
                          forDate:date].length;

3.3 根據(jù)給定時間點,計算在給定單位里的序數(shù),比如:當(dāng)前時間(5月1日) 是一年的第幾周,5月的第幾周,這個結(jié)果受minimumDaysInFirstWeek值的影響(不理解可以在看上文屬性介紹)

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

3.4 根據(jù)給定時間,計算該時間所在單位的起始日期(第一天)

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

例如:當(dāng)前時間5月3日,計算當(dāng)月起始天數(shù)

 NSDate *firstDate;
 NSTimeInterval timeInterval;
 if([calender rangeOfUnit:NSCalendarUnitMonth
                   startDate:&firstDate
                    interval:&timeInterval
                     forDate:NSDate.date]){
        NSLog(@"第一天是:%@",firstDate);
        NSLog(@"%f",timeInterval);
  }

獲取一周的第一天

NSDate *today = [[NSDate alloc] init];
NSDate *beginningOfWeek = nil;
BOOL ok = [gregorian rangeOfUnit:NSWeekCalendarUnit startDate:&beginningOfWeek interval:NULL forDate:today];
當(dāng)前日期在NSCalendarUnitMonth單位的起始日期:Sun May  3 00:00:00 2020
當(dāng)月所有天數(shù)的秒數(shù):604800

3.5 獲取給定時間的指定單位的值,比如:2020-5-1,單位 月,返回值是 5

-(NSInteger)component:(NSCalendarUnit)unit fromDate:(NSDate *)date

[NSCalendar.currentCalendar component:NSCalendarUnitMonth fromDate:NSDate.date];

3.6 自定義時間,通過 年代,年,月,日.是,分,秒等返回一個具體的date 例如:2020-6-5 12:30:00

-(nullable NSDate *)dateWithEra:(NSInteger)eraValue year:(NSInteger)yearValue month:(NSInteger)monthValue day:(NSInteger)dayValue hour:(NSInteger)hourValue minute:(NSInteger)minuteValue second:(NSInteger)secondValue nanosecond:(NSInteger)nanosecondValue

 [NSCalendar.currentCalendar dateWithEra:2
                                       year:2020
                                      month:6
                                        day:5
                                       hour:12
                                     minute:30
                                     second:0
                                 nanosecond:0];

3.7根據(jù)指定單位排序(比較大小),-1 升序,0 等于 1 降序
同樣可以用NSDate中earlierDate, laterDate方法比較

-(NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit

比如: 2020-5-4 和2020-5-6 返回-1

[NSCalendar.currentCalendar compareDate:date1 toDate:date2 toUnitGranularity:NSCalendarUnitDay]

3.8 根據(jù)指定的日歷單位,比較兩個日期是否在同一個單位內(nèi)

-(BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit

比如:比較2020-6-4和2020-6-5, 單位是 月 返回 YES,單位是 日 返回 NO

[NSCalendar.currentCalendar isDate:date2
                           equalToDate:NSDate.date
                     toUnitGranularity:NSCalendarUnitMonth]

3.9 從現(xiàn)在開始一個半小時后的時間

把一個日歷組件添加到現(xiàn)有時間
-(nullable NSDate *)dateByAddingComponents:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSCalendarOptions)opts;

 NSDate *today = [[NSDate alloc] init];
 NSCalendar *gregorian = [[NSCalendar alloc]    initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
 NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
 [offsetComponents setHour:1];
 [offsetComponents setMinute:30];
 NSDate *endOfWorldWar3 = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0];

3.10計算匹配(或最接近匹配)給定組件集的日期棍鳖,并枚舉匹配的結(jié)果

-(void)enumerateDatesStartingAfterDate:(NSDate *)start matchingComponents:(NSDateComponents *)comps options:(NSCalendarOptions)opts usingBlock:(void (NS_NOESCAPE ^)(NSDate * _Nullable date, BOOL exactMatch, BOOL *stop))block

參數(shù) start:起始日期;
參數(shù) comps日期組件(匹配模式)比如:閏年 2月29
參數(shù) opts 匹配規(guī)則(嚴(yán)格匹配還是模糊匹配),文檔中給的例子很詳細

//自定義日期組件
NSDateComponents *cusDateComponents = [NSDateComponents new];
cusDateComponents.month = 2;
cusDateComponents.day = 29;
    //匹配日期
[NSCalendar.currentCalendar enumerateDatesStartingAfterDate:NSDate.date matchingComponents:cusDateComponents options:NSCalendarMatchStrictly usingBlock:^(NSDate * _Nullable date, BOOL exactMatch, BOOL * _Nonnull stop) {
    NSLog(@"%@",date);
    if (exactMatch) {
        *stop = YES;//匹配成功,修改stop的值為YES停止
    }
}];

3.10給現(xiàn)有時間添加指定單位后得到一個新時間
比如,2020-6-5,給 天 的單位添加10 ,返回2020-6-15,也可以通過日歷組件NSDateComponents實現(xiàn)

-(nullable NSDate *)dateByAddingUnit:(NSCalendarUnit)unit value:(NSInteger)value toDate:(NSDate *)date options:(NSCalendarOptions)options

3.1指定當(dāng)前日期的某個單位的值,為NSDateComponents中對應(yīng)單位的值
比如:當(dāng)前時間2020-6-5,指定NSDateComponents中的 day = 10,那么返回2020-6-10

-(nullable NSDate *)nextDateAfterDate:(NSDate *)date matchingComponents:(NSDateComponents *)comps options:(NSCalendarOptions)options

直接通過日歷單位改設(shè)置對應(yīng)位置的值,效果和nextDateAfterDate一樣

-(nullable NSDate *)dateBySettingUnit:(NSCalendarUnit)unit value:(NSInteger)v ofDate:(NSDate *)date options:(NSCalendarOptions)opts

三炮叶、`NSDateComponents 可以用來表示特定日期的組成部分,例如小時渡处,分鐘镜悉,天,年等医瘫。

1.創(chuàng)建一個日期組件對象,例如:2020-5-3 14:00:00

 NSDateComponents *components = [[NSDateComponents alloc]init];
 components.year = 2020;
 components.month = 5;
 components.day =3;
 components.hour = 14;

2.NSDateNSDateComponents之間的相互轉(zhuǎn)換,需要用到NSCalendar類中的方法
NSDateComponents轉(zhuǎn)NSDate(必須確保指定組件在單位范圍內(nèi),比如,設(shè)置陽歷:2月30,會產(chǎn)生一個為定義的結(jié)果)

 NSDate *date = [[NSCalendar currentCalendar] dateFromComponents:components];

NSDate轉(zhuǎn)NSDateComponents

NSDate *today = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc]
                         initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents =
                    [gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:today];

3.將日期組件從一個日歷轉(zhuǎn)換為另一個,例如:陽歷轉(zhuǎn)換成農(nóng)歷
自定義一個陽歷時間:2020-6-5

NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:5];
[comps setMonth:6];
[comps setYear:2020];
NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *date = [gregorian dateFromComponents:comps];

轉(zhuǎn)換成農(nóng)歷年

NSCalendar *chineseCalender = [[NSCalendar alloc]
                          initWithCalendarIdentifier:NSCalendarIdentifierChinese];
NSUInteger unitFlags = NSCalendarUnitDay | NSCalendarUnitMonth |NSCalendarUnitYear;
NSDateComponents *components = [chineseCalender components:unitFlags fromDate:date];
NSLog(@"%ld-%ld-%ld",(long)[components year],(long)[components month],(long)[components day]);

查了一下農(nóng)歷確實是:庚子年閏四月十四( 第37年稱“庚子年”)

37-4-14

四侣肄、NSDateFormatter 時間格式化指南

最常見的用法,時間字符串之間的互轉(zhuǎn)
時間轉(zhuǎn)字符串:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yy-MM-dd"];
NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
NSLog(@"dateString:%@",dateString);

字符串轉(zhuǎn)時間

NSDateFormatter *stringDate = [[NSDateFormatter alloc] init];
[stringDate setDateFormat:@"yyyy-MM-dd"];
NSDate *date = [stringDate dateFromString:@"2020-05-31"];
NSLog(@"date:%@",date);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市醇份,隨后出現(xiàn)的幾起案子稼锅,更是在濱河造成了極大的恐慌,老刑警劉巖僚纷,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件矩距,死亡現(xiàn)場離奇詭異,居然都是意外死亡怖竭,警方通過查閱死者的電腦和手機锥债,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痊臭,“玉大人哮肚,你說我怎么就攤上這事」愠祝” “怎么了绽左?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長艇潭。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么蹋凝? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任鲁纠,我火速辦了婚禮,結(jié)果婚禮上鳍寂,老公的妹妹穿的比我還像新娘改含。我一直安慰自己,他們只是感情好迄汛,可當(dāng)我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布捍壤。 她就那樣靜靜地躺著,像睡著了一般鞍爱。 火紅的嫁衣襯著肌膚如雪鹃觉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天睹逃,我揣著相機與錄音盗扇,去河邊找鬼。 笑死沉填,一個胖子當(dāng)著我的面吹牛疗隶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播翼闹,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼斑鼻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了猎荠?” 一聲冷哼從身側(cè)響起坚弱,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎法牲,沒想到半個月后史汗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡拒垃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年停撞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悼瓮。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡戈毒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出横堡,到底是詐尸還是另有隱情埋市,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布命贴,位于F島的核電站道宅,受9級特大地震影響食听,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜污茵,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一樱报、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泞当,春花似錦迹蛤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至陋桂,卻和暖如春逆趣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背章喉。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工汗贫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秸脱。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓落包,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摊唇。 傳聞我的和親對象是個殘疾皇子咐蝇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,554評論 2 349