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ù)的不算做一周
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.NSDate
和NSDateComponents
之間的相互轉(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);