本文不讲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
网友评论