本文不讲UI,用打印台来输出日历。
在显示日历的时候,我们只需要传入参数年月即可,加上日期可以定位到当天在日历上的显示。
日历的显示排版一般是7x5或7x4,每一行从周日开始,周六结束,像这样:
屏幕快照 2018-06-07 17.14.22.png
当我们要显示某个月份的时候,我们必需获取到下面这些值:
1.当月第一天是周几;
2.当月总天数
有了这两条数据我们就可以显示出一个粗糙的日历了,但是有一点,假如当月第一天不是周一,如上图,那么前面几天的日期如何显示呢?所以我们会需要多一条数据:上个月份的总天数,通过简单的加减就能显示了,下面开始通过代码了解如何制作一个日历。
我直接贴上代码吧:
//根据date获取日- (NSInteger)convertDateToDay:(NSDate *)date { NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitDay) fromDate:date]; return [components day]; }//根据date获取月- (NSInteger)convertDateToMonth:(NSDate *)date { NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitMonth) fromDate:date]; return [components month]; }//根据date获取年- (NSInteger)convertDateToYear:(NSDate *)date { NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitYear) fromDate:date]; return [components year]; }//根据date获取当月周几 (美国时间周日-周六为 1-7,改为0-6方便计算)- (NSInteger)convertDateToWeekDay:(NSDate *)date { NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitWeekday fromDate:date]; NSInteger weekDay = [components weekday] - 1; weekDay = MAX(weekDay, 0); return weekDay; }//根据date获取当月周几- (NSInteger)convertDateToFirstWeekDay:(NSDate *)date { NSCalendar *calendar = [NSCalendar currentCalendar]; [calendar setFirstWeekday:1];//1.Sun. 2.Mon. 3.Thes. 4.Wed. 5.Thur. 6.Fri. 7.Sat. NSDateComponents *comp = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:date]; [comp setDay:1]; NSDate *firstDayOfMonthDate = [calendar dateFromComponents:comp]; NSUInteger firstWeekday = [calendar ordinalityOfUnit:NSCalendarUnitWeekday inUnit:NSCalendarUnitWeekOfMonth forDate:firstDayOfMonthDate]; return firstWeekday - 1; //美国时间周日为星期的第一天,所以周日-周六为1-7,改为0-6方便计算}//根据date获取当月总天数- (NSInteger)convertDateToTotalDays:(NSDate *)date { NSRange daysInOfMonth = [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date]; return daysInOfMonth.length; }
在获取周几的时候要注意一点,美国时间是星期日作为一周的第一天,所以通过函数回调的值,周日-周六是为1-7的,为了方便计算,我进行了-1操作。
接下来是获取上个月份的数据:
//根据date获取偏移指定天数的date- (NSDate *)getDateFrom:(NSDate *)date offsetDays:(NSInteger)offsetDays { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyy-MM"]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *lastMonthComps = [[NSDateComponents alloc] init]; [lastMonthComps setDay:offsetDays]; //year = 1表示1年后的时间 year = -1为1年前的日期,month day 类推 NSDate *newdate = [calendar dateByAddingComponents:lastMonthComps toDate:date options:0]; return newdate; }//根据date获取偏移指定月数的date- (NSDate *)getDateFrom:(NSDate *)date offsetMonths:(NSInteger)offsetMonths { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyy-MM"]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *lastMonthComps = [[NSDateComponents alloc] init]; [lastMonthComps setMonth:offsetMonths]; //year = 1表示1年后的时间 year = -1为1年前的日期,month day 类推 NSDate *newdate = [calendar dateByAddingComponents:lastMonthComps toDate:date options:0]; return newdate; }//根据date获取偏移指定年数的date- (NSDate *)getDateFrom:(NSDate *)date offsetYears:(NSInteger)offsetYears { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyy"]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *lastMonthComps = [[NSDateComponents alloc] init]; [lastMonthComps setYear:offsetYears]; //year = 1表示1年后的时间 year = -1为1年前的日期,month day 类推 NSDate *newdate = [calendar dateByAddingComponents:lastMonthComps toDate:date options:0]; return newdate; }
有了这几个函数,就能具备制作一个日历的数据支持了,接下来的代码可以自行复制输出:
- (void)test { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd"]; for (int i = 1; i <= 12; i++) { NSString *string = [NSString stringWithFormat:@"2018-%02d-01",i]; NSDate *date = [dateFormatter dateFromString:string]; [self logCalendarWith:date]; } } - (void)logCalendarWith:(NSDate *)date { NSInteger year = [self convertDateToYear:date]; NSInteger month = [self convertDateToMonth:date]; NSInteger day = [self convertDateToDay:date]; NSInteger firstWeekDay = [self convertDateToFirstWeekDay:date]; NSInteger totalDays = [self convertDateToTotalDays:date]; printf("第%ld月\n",month); NSInteger line = totalDays <= 28 ? 4 : 5; NSInteger column = 7; NSInteger available = 1; //超过总天数后为下月 NSInteger nextMonthDay = 1; //下月天数开始计数 NSDate *lastMonthDate = [self getDateFrom:date offsetMonths:-1]; //上月月数 NSInteger lastMonthTotalDays = [self convertDateToTotalDays:lastMonthDate]; //上月天数计数 for (int i = 0; i < line; i++) { for (int j = 0; j < column; j++) { if (available > totalDays) { printf("\t%ld ",nextMonthDay++); continue; } if (i == 0 && j < firstWeekDay) { NSInteger lastMonthDay = lastMonthTotalDays - firstWeekDay + j + 1; //j从0开始,所以这里+1 printf("\t%ld ",lastMonthDay); }else { printf("\t%ld",available++); } } printf("\n"); } printf("\n"); printf("\n"); }
想要测试年份、月份、日的准确性的话,就在test函数里面自行修改就好了,如果没有问题,打印台就有下面的显示:
屏幕快照 2018-09-26 17.15.03.png
作者:Double_Chen
链接:https://www.jianshu.com/p/b7d0023c0bdf