为了账号安全,请及时绑定邮箱和手机立即绑定

iOS NSCalendar的使用,制作日历

标签:
iOS

本文不讲UI,用打印台来输出日历。

在显示日历的时候,我们只需要传入参数年月即可,加上日期可以定位到当天在日历上的显示。

日历的显示排版一般是7x5或7x4,每一行从周日开始,周六结束,像这样:


webp

屏幕快照 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函数里面自行修改就好了,如果没有问题,打印台就有下面的显示:

webp

屏幕快照 2018-09-26 17.15.03.png



作者:Double_Chen
链接:https://www.jianshu.com/p/b7d0023c0bdf


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消