NSCalendar相关

######先说下需求:选择日期弹出日历(跟途牛,携程等差不多就行。。。行)

初识NSCalendar到写完日历的感受:

懵+1

什么鬼?

如此强大的日历类

果然利弊都有,虽然很强大,但是极其耗内存

一组表情表示写日历过程中的心情或者每天的心情(同意的猿/媛点赞):

我的一天.png

先来点湿的(很湿很能吹...)

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中,第一次取得以后如果用户修改该系统日历设定,这个值也不会改变。

NSCalendar  * calendar = [NSCalendar currentCalendar];

//如果用autoupdatingCurrentCalendar,那么每次取得的值都会是当前系统设置的日历的值。

NSCalendar  * autoupdatingCurrent = [NSCalendar autoupdatingCurrentCalendar];

//- initWithCalendarIdentifier:

//如果想要用公历的时候,就要将NSDateFormatter的日历设置成公历。否则随着用户的系统设置的改变,取得的日期的格式也会不一样。

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

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

[formatter setCalendar:initCalendar];

NSCalendar官方API翻译:

NSCalendar对象封装了有关计算时间的系统的信息,其中定  义了年的开始,长度和分割。它们提供关于日历的信息和对日历计算的支持,例如确定给定的日历单元的范围和将单位添加到给定的绝对时间

由此能理解数学英语都辣鸡的我看到它有多懵,NSCalendar功能很强大,还有一点就是我写完日历后,界面会非常卡。最终发现是这个NSCalendar特别特别耗内存。最好能写成全局变量来使用。

是时候来点干的了(聊一些我工作用到的类和一些封装的方法)

先上效果图瞅瞅(类似途牛的日历,没有选择后标记):

calendarTop.png

calendarBottom.png

1.获取当前月份有多少天:

-(NSInteger)getCurrentMonthForDays{

// 创建一个日期类对象(当前月的calendar对象)

NSCalendar *calendar = [NSCalendar currentCalendar];

// NSRange是一个结构体,其中location是一个以0为开始的index,length是表示对象的长度。他们都是NSUInteger类型。

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

NSUInteger numberOfDaysInMonth = range.length;

return numberOfDaysInMonth;

}

2获取目标月份的天数:

-(NSInteger)getNextNMonthForDays:(NSDate)date

{

NSCalendar * calendar = [NSCalendar currentCalendar];

// 调用rangeOfUnit方法:(返回一样是一个结构体)两个参数一个大单位,一个小单位(.length就是天数,.location就是月)

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

return monthNum;

}

3.获取一个目标date(包含某个月的1号数据),或者说获取某个月的1号的date对象

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

// 指定日历单位,如日期和月份。(这里指定了年月日,还有其他字段添加单位.特别齐全 :世纪,年月日时分秒等等等)

NSCalendarUnit dayInfoUnits  = NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;

// NSDateComponents封装了日期的组件,年月日时分秒等(个人感觉像是平时用的model模型)

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

// 指定1号

components.day = 1;

// 指定月份(我这里是获取当前月份的下1个月的1号的date对象,所以用的++,其上个月或者其他同理)

components.month++;

// 转成需要的date对象return

NSDate * nextMonthDate =[calendar dateFromComponents:components];

return nextMonthDate;

}

(用到的API基本注释完了下边就不那么多注释了)纯属个人理解,如发现错误的地方请指正,大家共同进步.

4.获取某个月的1号是星期几(必不可少的一个方法,用来布局UI使每月1号与星期队形起来):

-(NSInteger)getFirstDayWeekForMonth:(NSDate*)date

{

// NSCalendarIdentifierGregorian : 指定日历的算法

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

// NSDateComponents封装了日期的组件,年月日时分秒等(个人感觉像是平时用的model模型)

// 调用NSCalendar的components:fromDate:方法返回一个NSDateComponents对象

// 需要的参数分别components:所需要的日期单位 date:目标月份的date对象

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

NSLog(@"NSDateComponents是这个样子的:%@",comps);

// 直接调用自己weekDay属性

NSInteger weekday = [comps weekday];

#warning mark --找了很多原因不知道为什么星期数总是比实际快一天,有时间找更好的解决方法(暂时用-1天处理了)

weekday--;

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

if (weekday == 7) {

return 0;

}else return weekday;

}

5. 当前时间与之前时间的间隔:

/**

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

*  @brief  获取一个标准时间戳与当前时间的时间差

*  @param tinterval 时间戳

*  @return 距离当前时间的时间间隔

*/

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

//进行时间差比较

//当前时间与1970时间戳(秒为单位)

NSTimeInterval time = [[NSDate date] timeIntervalSince1970];

// 当前时间戳-当时时间戳=差值(比如朋友圈动态发表时间为10分钟前(当前时间-发表时间))

NSTimeInterval timeInterval = time-interval;

//计算出天、小时、分钟

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.获取当前系统时间:

-(NSString *)getCurrentTime{

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

// 格式化系统时间字符串

[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互相转换:

// date对象转换成字符串(最后return根据自己需求处理)

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

{

NSDateFormatter* dateFormat = [[NSDateFormatter alloc] init];//实例化一个NSDateFormatter对象

[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//设定时间格式,这里可以设置成自己需要的格式

NSString *currentDateStr = [dateFormat stringFromDate:date];

// 根据自己需求处理字符串

return [currentDateStr substringToIndex:7];

}

// NSString对象转date

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

{

//设置转换格式

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

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

NSDate *date=[formatter dateFromString:str];

return date;

}

8个方法差不多能够实现一个简单点的日历控件了,88大发,大功告成。2017第一篇,比较偏基础适合我这种菜鸟或者新手,大神路过的话就当娱乐一下了。有错误的话希望多多指点楼主一下

下面贴一下代码以及实现思路:

思路:

刚知道要写日历的时候是懵逼的,对NSdate还好、NSCalendar完全没有概念。查了挺多资料,也在github找了好几个demo想直接拿过来用,不过不太合适所以决定自己写。试了tableView、跟colelctionView,最后选择collectionView需求是展示当前月跟之后三个月的日历。

所以就:

区头实现星期View->四个分区->区头区尾配合实现效果,上边聊得几个方法处理DataSource.

日历中标记今天的思路是:

实例变量selectedIndex(今天的下标): ---实现->(获取到今天几号,加上今天周几-1就是日历中今天那个cell所在的位置了)

直接截图代码:

都比较基础(自己保存下笔记,也分享给能用到的童鞋)

UICollectionView实现:

collectionView.png

DataSource:每个分区返回item数量

dataSource返回item个数.png

DataSource: 绘制item

dateSource绘制Cell.png

DataSource:headerView和footerView以及点击回传数据:

区头、区尾、点击.png

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

作者:cocoaAhda

链接:http://www.jianshu.com/p/41ab0eaa78ef

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



说一点题外话,提交appstore的时候,如果你的历法类初始化用的是【NSCalendar  * calendar = [NSCalendar currentCalendar],好像苹果会给你驳回,表示你需要添加一个获取日历权限的key。

而且我在MJRefresh里也看到了一段相同意思的注释。所以要么去乖乖的加权限,要么换对应identifier的初始化方法吧。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容