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

需求

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

算法讨论:获取上个月第一天到今天的信息_第1张图片
需求图片

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

//接口返回数据结构
"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;
},
,
,
,
{
    monthStr = 3;
},
,
,
,
......

上代码
//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】首条是否是当天,如果是当天直接使用,不用走第二步,节省点计算时间。

你可能感兴趣的:(算法讨论:获取上个月第一天到今天的信息)