美文网首页
算法讨论:获取上个月第一天到今天的信息

算法讨论:获取上个月第一天到今天的信息

作者: 淘码小工 | 来源:发表于2018-04-01 16:34 被阅读24次
    需求

    这两个获取一个需求,需要做一个打卡列表,显示上个月所有打卡的信息,及这个月到今天的的打卡信息,并且标注出来月份。设计界面大致如此:

    需求图片

    后台接口只能返回已经打卡的信息。如果当天没有打卡,是不返回的。

    //接口返回数据结构
    "data": [
            {
                "signLastTime": 1522199821084,                 //当天最后一次打卡时间
                "signMonth": 3,                                 //当天属于几月
                "week": "周三",                                 //当天属于周几
                "inDate": 1522199817934,                       //数据库返回时间,本地无用
                "signDay": 28,                                 //当天属于几号
                "signItems": [                                 //当天打卡次数,返回每次打卡数据
                    {
                        "longitude": 123566,          //经度
                        "signAdress": "北京市海淀区上地地铁口",   //地址
                        "signTime": 1522199817934,        //打卡时间
                        "latitude": 456233           //纬度
                    },
                    {
                        "longitude": 456233,
                        "signAdress": "北京市海淀区西直门地铁口",
                        "signTime": 1522199821084,
                        "latitude": 123566
                    }
                ],
                "reDate": 1522199821084,      //数据库返回时间,无用
                "signYear": 2018,                      //本次打卡数据年份
                "id": "5abaed0923130b394c1e10ce",      //id
                "signFirstTime": 1522199817934,            //当天首次打卡时间
                "userId": 111225,                   //打卡人id
                "status": 1                             //客户端无用
            }
    

    大家可以先不看我的解决方法,自己思考一下如何来写这个算法,才能达到最优。


    我的解决方案

    声明一下,我的解决方案可能不是最优的,如果有好的想法,我们在留言可以一起讨论。

    1. 按照后台接口返回,创建model类。
    2. 创建一个config类,通过后台返回数据,返回能被tableView解析显示的数据。

    config作为配置类,所有的算法配置写在这个类中。类大概是

    思路:
    1. 通过获取当月到今天的天数 currentMonthDay,在获取上个月总天数lastMonthDay。
    2. 使用for循环来循环,次数 = currentMonthDay + lastMonthDay, 来生成一个只包含'yyyy-MM-dd'字符串类型的数组【数组A】,生成一个字典包含key: 是上面的字符串,value:model的类【字典A】
    3. 使用for循环, 次数 = punchList.count ,已经打卡的天数。再通过打卡时某一天,替换上面字典A中的value:model值。
    4. 通过for循环【数组A】,来获取【字典A】中的model值,生成一个新的数组【数组B】。使用这一步主要是确保时间的顺序。
    5. 返回【数组B】就是需要的这两个月的打卡数据model数组
      6 通过在index = 0处插入当月的月份,在 index = currentMonthDay +1 处插入上个月的月份。就生成了需要的结果。

    结果类型

    {
        monthStr = 4;
    },
    <NTOutdoorPunchInfoModel: 0x10eb40830>,
    <NTOutdoorPunchInfoModel: 0x10eb3f6b0>,
    <NTOutdoorPunchInfoModel: 0x10eb1da40>,
    {
        monthStr = 3;
    },
    <NTOutdoorPunchInfoModel: 0x10ec4e810>,
    <NTOutdoorPunchInfoModel: 0x10ec1dc40>,
    <NTOutdoorPunchInfoModel: 0x108896f00>,
    ......
    
    
    上代码
    //config.m
    @property (nonatomic, strong)NSMutableDictionary *monthDicInfo;
    
    //public 对外放开接口的类,主要是来配置解析数据的方法
    - (NSArray *)configForPunchList:(NSArray *)punchList {
        // 1. 首先创建返回解析好的数组,作为返回值返回
       NSMutableArray *monthInfo = [[NSMutableArray alloc] init];
       //2. 调用getMonthList 来获取一个数组(备注1)和一个字典(备注2)
       NSArray *monthList = [self getMonthList];
      //3.  for 循环 服务器返回的数据,来更
    for (NSDictionary *dic in punchList) {
            NTOutdoorPunchInfoModel *model = [NTOutdoorPunchInfoModel getModelFromDic:dic];
            NSTimeInterval firstTimePunch = model.signFirstTime;
            NSString *timeStr = [TimeUtil getDateStr:firstTimePunch/1000];
            [self.monthDicInfo setValue:model forKey:timeStr];
        }
    
        //4. 确定今天是几月,通过今天是几月,得出上个月是几月,设置保存上个月的一个字典
        NSInteger nowMonthInt = [self getYearOrMonthOrDayForDate:[NSDate date] calendarUnit:NSCalendarUnitMonth];
        NSInteger lastMonthInt = (nowMonthInt == 1) ? 12 : nowMonthInt -1;
        NSDictionary *nowMonthDic = @{@"monthStr":[NSString stringWithFormat:@"%ld",(long)nowMonthInt]};
        NSDictionary *lastMonthDic = @{@"monthStr":[NSString stringWithFormat:@"%ld",(long)lastMonthInt]};
       [monthInfo addObject:nowMonthDic];
    // 5. for循环备注1的数组,通过key值,顺序获取备注2中的model值,保存到monthInfoList
     for (NSString *timeStr in monthList) {
            NTOutdoorPunchInfoModel *model = [self.monthDicInfo objectForKey:timeStr];
            [monthInfo addObject:model];
        }
       //6. 确定几天是几号,在monthInfoList插入到index = nowDay + 1数组中去
     NSInteger nowDay = [self getYearOrMonthOrDayForDate:[NSDate date] calendarUnit:NSCalendarUnitDay];
        [monthInfo insertObject:lastMonthDic atIndex:nowDay + 1];
        return monthInfo;
      //7. 返回配置好的 
       return   monthInfoList
    }
    
    //private
    //返回一个字符串数组,数组包括从当天开始到上个月1号的日期,格式yyyy-MM-dd
    //并且创建了一个字典,key是yyyy-MM-dd的日期字符串,value是model类
    - (NSMutableArray *)getMonthList { 
        NSMutableArray *monthList = [[NSMutableArray alloc] init];
        
        NSDate *currentDate = [NSDate date];
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"yyyy-MM-dd"];
        NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
        NSDateComponents *lastMonthComps = [[NSDateComponents alloc] init];
        //当月现在是几日
        NSInteger nowDay = [self getYearOrMonthOrDayForDate:[NSDate date] calendarUnit:NSCalendarUnitDay];
        NSInteger lastMonthDays = [self getDaysWithLastMonth];
        int count = 0;
        for (NSInteger i = nowDay+lastMonthDays; i > 0; i --) {
            //    [lastMonthComps setYear:1]; // year = 1表示1年后的时间 year = -1为1年前的日期,month day 类推
            [lastMonthComps setDay:-count];
            NSDate *newdate = [calendar dateByAddingComponents:lastMonthComps toDate:currentDate options:0];
            NSString *dateStr = [formatter stringFromDate:newdate];
            [monthList addObject:dateStr];
            
            //保存每个model
            NTOutdoorPunchInfoModel *model = [[NTOutdoorPunchInfoModel alloc] init];
            model.signYear = [NSString stringWithFormat:@"%ld",(long)[self getYearOrMonthOrDayForDate:newdate calendarUnit:NSCalendarUnitYear]];
            model.signMonth = [NSString stringWithFormat:@"%ld",(long)[self getYearOrMonthOrDayForDate:newdate calendarUnit:NSCalendarUnitMonth]];
            model.signDay = [NSString stringWithFormat:@"%ld",(long)[self getYearOrMonthOrDayForDate:newdate calendarUnit:NSCalendarUnitDay]];
            model.week = [self getWeekStrForDate:newdate];
            [self.monthDicInfo setValue:model forKey:dateStr];
            count++;
        }
        return monthList;
    }
    
    //private
    //通过一个日期字符串返回date
    - (NSDate *)getDateWithDateStr:(NSString *)str {}
    
    //private
    //获取上个月有多少天
    - (NSInteger)getDaysWithLastMonth {}
    
    //private
    //根据date日期,和calendarUnit返回date属于哪一年,月,日
    - (NSInteger)getYearOrMonthOrDayForDate:(NSDate *)date calendarUnit:(NSCalendarUnit)unit {
    }
    
    //private
    //根据date日期获取是周几,转化为例如'星期天' 表达
    - (NSString *)getWeekStrForDate:(NSDate *)date {}
    
    结尾:

    可以优化的地方:如果当天多次进入到这个页面,可以把获取的【数组A】【字典A】缓存一下,每次进来查看【数组A】首条是否是当天,如果是当天直接使用,不用走第二步,节省点计算时间。

    相关文章

      网友评论

          本文标题:算法讨论:获取上个月第一天到今天的信息

          本文链接:https://www.haomeiwen.com/subject/kloocftx.html