NSCalendar相關(guān)

######先說下需求:選擇日期彈出日歷(跟途牛,攜程等差不多就行。。。行)

初識NSCalendar到寫完日歷的感受:

懵+1

什么鬼?

如此強(qiáng)大的日歷類

果然利弊都有,雖然很強(qiáng)大,但是極其耗內(nèi)存

一組表情表示寫日歷過程中的心情或者每天的心情(同意的猿/媛點(diǎn)贊):

我的一天.png

先來點(diǎn)濕的(很濕很能吹...)

NSCalendar官方API:

NSCalendar objects encapsulate information about systems of reckoning time in which the beginning, length, and divisions of a year are defined. They provide information about the calendar and support for calendrical computations such as determining the range of a given calendrical unit and adding units to a given absolute time

NSCalendar的初始化方法:

常用:

// 可指定日歷的算法

NSCalendar? * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

// currentCalendar取得的值會一直保持在cache中,第一次取得以后如果用戶修改該系統(tǒng)日歷設(shè)定,這個值也不會改變。

NSCalendar? * calendar = [NSCalendar currentCalendar];

//如果用autoupdatingCurrentCalendar,那么每次取得的值都會是當(dāng)前系統(tǒng)設(shè)置的日歷的值。

NSCalendar? * autoupdatingCurrent = [NSCalendar autoupdatingCurrentCalendar];

//- initWithCalendarIdentifier:

//如果想要用公歷的時候,就要將NSDateFormatter的日歷設(shè)置成公歷。否則隨著用戶的系統(tǒng)設(shè)置的改變,取得的日期的格式也會不一樣。

NSCalendar *initCalendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;

[formatter setCalendar:initCalendar];

NSCalendar官方API翻譯:

NSCalendar對象封裝了有關(guān)計(jì)算時間的系統(tǒng)的信息,其中定? 義了年的開始,長度和分割。它們提供關(guān)于日歷的信息和對日歷計(jì)算的支持,例如確定給定的日歷單元的范圍和將單位添加到給定的絕對時間

由此能理解數(shù)學(xué)英語都辣雞的我看到它有多懵,NSCalendar功能很強(qiáng)大,還有一點(diǎn)就是我寫完日歷后,界面會非常卡。最終發(fā)現(xiàn)是這個NSCalendar特別特別耗內(nèi)存。最好能寫成全局變量來使用。

是時候來點(diǎn)干的了(聊一些我工作用到的類和一些封裝的方法)

先上效果圖瞅瞅(類似途牛的日歷,沒有選擇后標(biāo)記):

calendarTop.png

calendarBottom.png

1.獲取當(dāng)前月份有多少天:

-(NSInteger)getCurrentMonthForDays{

// 創(chuàng)建一個日期類對象(當(dāng)前月的calendar對象)

NSCalendar *calendar = [NSCalendar currentCalendar];

// NSRange是一個結(jié)構(gòu)體,其中l(wèi)ocation是一個以0為開始的index,length是表示對象的長度。他們都是NSUInteger類型。

NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:[NSDate date]];

NSUInteger numberOfDaysInMonth = range.length;

return numberOfDaysInMonth;

}

2獲取目標(biāo)月份的天數(shù):

-(NSInteger)getNextNMonthForDays:(NSDate)date

{

NSCalendar * calendar = [NSCalendar currentCalendar];

// 調(diào)用rangeOfUnit方法:(返回一樣是一個結(jié)構(gòu)體)兩個參數(shù)一個大單位,一個小單位(.length就是天數(shù),.location就是月)

NSInteger monthNum = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date].length;

return monthNum;

}

3.獲取一個目標(biāo)date(包含某個月的1號數(shù)據(jù)),或者說獲取某個月的1號的date對象

-(NSDate *)getAMonthframDate:(NSDate*)date {

// 指定日歷單位,如日期和月份。(這里指定了年月日,還有其他字段添加單位.特別齊全 :世紀(jì),年月日時分秒等等等)

NSCalendarUnit dayInfoUnits? = NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;

// NSDateComponents封裝了日期的組件,年月日時分秒等(個人感覺像是平時用的model模型)

NSDateComponents *components = [calendar components: dayInfoUnits fromDate:date];

// 指定1號

components.day = 1;

// 指定月份(我這里是獲取當(dāng)前月份的下1個月的1號的date對象,所以用的++,其上個月或者其他同理)

components.month++;

// 轉(zhuǎn)成需要的date對象return

NSDate * nextMonthDate =[calendar dateFromComponents:components];

return nextMonthDate;

}

(用到的API基本注釋完了下邊就不那么多注釋了)純屬個人理解,如發(fā)現(xiàn)錯誤的地方請指正,大家共同進(jìn)步.

4.獲取某個月的1號是星期幾(必不可少的一個方法,用來布局UI使每月1號與星期隊(duì)形起來):

-(NSInteger)getFirstDayWeekForMonth:(NSDate*)date

{

// NSCalendarIdentifierGregorian : 指定日歷的算法

NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

// NSDateComponents封裝了日期的組件,年月日時分秒等(個人感覺像是平時用的model模型)

// 調(diào)用NSCalendar的components:fromDate:方法返回一個NSDateComponents對象

// 需要的參數(shù)分別components:所需要的日期單位 date:目標(biāo)月份的date對象

NSDateComponents *comps = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitWeekday fromDate:date];

NSLog(@"NSDateComponents是這個樣子的:%@",comps);

// 直接調(diào)用自己weekDay屬性

NSInteger weekday = [comps weekday];

#warning mark --找了很多原因不知道為什么星期數(shù)總是比實(shí)際快一天,有時間找更好的解決方法(暫時用-1天處理了)

weekday--;

NSLog(@"[comps weekday] = %ld",(long)weekday);

if (weekday == 7) {

return 0;

}else return weekday;

}

5. 當(dāng)前時間與之前時間的間隔:

/**

*? @author jaki, 15-09-21 17:09:42

*? @brief? 獲取一個標(biāo)準(zhǔn)時間戳與當(dāng)前時間的時間差

*? @param tinterval 時間戳

*? @return 距離當(dāng)前時間的時間間隔

*/

-(NSString *)getStandardTimeInterval:(NSTimeInterval)interval{

//進(jìn)行時間差比較

//當(dāng)前時間與1970時間戳(秒為單位)

NSTimeInterval time = [[NSDate date] timeIntervalSince1970];

// 當(dāng)前時間戳-當(dāng)時時間戳=差值(比如朋友圈動態(tài)發(fā)表時間為10分鐘前(當(dāng)前時間-發(fā)表時間))

NSTimeInterval timeInterval = time-interval;

//計(jì)算出天、小時、分鐘

int day = timeInterval/(60*60*24);

int hour = ((long)timeInterval%(60*60*24))/(60*60);

int minite = ((long)timeInterval%(60*60*24))%(60*60)/60;

NSMutableString * timeStr = [[NSMutableString alloc]init];

// 邏輯判斷

if (day!=0) {

[timeStr appendString:[NSString stringWithFormat:@"%d天前",day]];

}else{

if (hour!=0) {

[timeStr appendString:[NSString stringWithFormat:@"%d小時前",hour]];

}else{

if (minite<1) {

[timeStr appendString:@"剛剛"];

}else{

[timeStr appendString:[NSString stringWithFormat:@"%d分鐘前",minite]];

}

}

}

return timeStr;

}

6.獲取當(dāng)前系統(tǒng)時間:

-(NSString *)getCurrentTime{

NSDateFormatter * formatter = [[NSDateFormatter alloc]init];

// 格式化系統(tǒng)時間字符串

[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSString * time = [formatter stringFromDate:[NSDate date]];

return time;

}

7.返回年月日時分秒:

#pragma mark --- 對比上邊就比較簡單了不過多啰嗦

-(int)getYear{

NSCalendar *calendar = [NSCalendar currentCalendar];

NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;

NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];

return (int)dateComponent.year;

}

-(int)getMonth{

NSCalendar *calendar = [NSCalendar currentCalendar];

NSUInteger unitFlags =? NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;

NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];

return (int)dateComponent.month;

}

-(int)getDay{

NSCalendar *calendar = [NSCalendar currentCalendar];

NSUInteger unitFlags =? NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;

NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];

return (int)dateComponent.day;

}

-(int)getHour{

NSCalendar *calendar = [NSCalendar currentCalendar];

NSUInteger unitFlags =? NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;

NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];

return (int)dateComponent.hour;

}

-(int)getMinute{

NSCalendar *calendar = [NSCalendar currentCalendar];

NSUInteger unitFlags =? NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;

NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];

return (int)dateComponent.minute;

}

-(int)getSecond{

NSCalendar *calendar = [NSCalendar currentCalendar];

NSUInteger unitFlags =? NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;

NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:self];

return (int)dateComponent.second;

}

8.date對象NSString互相轉(zhuǎn)換:

// date對象轉(zhuǎn)換成字符串(最后return根據(jù)自己需求處理)

-(NSString * )theTargetDateConversionStr:(NSDate * )date

{

NSDateFormatter* dateFormat = [[NSDateFormatter alloc] init];//實(shí)例化一個NSDateFormatter對象

[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//設(shè)定時間格式,這里可以設(shè)置成自己需要的格式

NSString *currentDateStr = [dateFormat stringFromDate:date];

// 根據(jù)自己需求處理字符串

return [currentDateStr substringToIndex:7];

}

// NSString對象轉(zhuǎn)date

-(NSDate* )theTargetStringConversionDate:(NSString *)str

{

//設(shè)置轉(zhuǎn)換格式

NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;

[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

NSDate *date=[formatter dateFromString:str];

return date;

}

8個方法差不多能夠?qū)崿F(xiàn)一個簡單點(diǎn)的日歷控件了,88大發(fā),大功告成。2017第一篇,比較偏基礎(chǔ)適合我這種菜鳥或者新手,大神路過的話就當(dāng)娛樂一下了。有錯誤的話希望多多指點(diǎn)樓主一下

下面貼一下代碼以及實(shí)現(xiàn)思路:

思路:

剛知道要寫日歷的時候是懵逼的,對NSdate還好、NSCalendar完全沒有概念。查了挺多資料,也在github找了好幾個demo想直接拿過來用,不過不太合適所以決定自己寫。試了tableView、跟colelctionView,最后選擇collectionView需求是展示當(dāng)前月跟之后三個月的日歷。

所以就:

區(qū)頭實(shí)現(xiàn)星期View->四個分區(qū)->區(qū)頭區(qū)尾配合實(shí)現(xiàn)效果,上邊聊得幾個方法處理DataSource.

日歷中標(biāo)記今天的思路是:

實(shí)例變量selectedIndex(今天的下標(biāo)): ---實(shí)現(xiàn)->(獲取到今天幾號,加上今天周幾-1就是日歷中今天那個cell所在的位置了)

直接截圖代碼:

都比較基礎(chǔ)(自己保存下筆記,也分享給能用到的童鞋)

UICollectionView實(shí)現(xiàn):

collectionView.png

DataSource:每個分區(qū)返回item數(shù)量

dataSource返回item個數(shù).png

DataSource: 繪制item

dateSource繪制Cell.png

DataSource:headerView和footerView以及點(diǎn)擊回傳數(shù)據(jù):

區(qū)頭、區(qū)尾、點(diǎn)擊.png

demo地址:https://github.com/rundonkey/DzNSCalendar.git

作者:cocoaAhda

鏈接:http://m.itdecent.cn/p/41ab0eaa78ef

來源:簡書

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。



說一點(diǎn)題外話,提交appstore的時候,如果你的歷法類初始化用的是【NSCalendar? * calendar = [NSCalendar currentCalendar],好像蘋果會給你駁回,表示你需要添加一個獲取日歷權(quán)限的key。

而且我在MJRefresh里也看到了一段相同意思的注釋。所以要么去乖乖的加權(quán)限,要么換對應(yīng)identifier的初始化方法吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容