背景
工作中在做某个业务需求的时候,某同事的实现,遇到了一个NSCalendar
进行日期转换卡顿的问题。
最后分析发现是调用了NSCalendar
的转换方法导致的,使用此方法是为了计算某个时间戳是否在某个区间内。
比如判断时间戳是美股盘前(夏令时:16:00~21:30)
使用NSCalendar实现
方法
- 将时间戳转换为
NSdate
- 使用
NSCalendar
将date
转换为NSDateComponents
- 使用
NSDateComponents
中的hour
、minute
判断是否否和区间
代码
- (BOOL)timeStamp1:(uint32_t)timeStamp betweenFromHour:(NSInteger)fromHour fromMinute:(NSInteger)fromMinute toHour:(NSInteger)toHour toMinute:(NSInteger)toMinute {
NSDate *date = [[NSDate alloc] initWithTimeIntervalSince1970:timeStamp];
NSCalendar *calendar = [NSCalendar currentCalendar]; // 注意:这里每次创建都会耗性能,考虑使用技能变量
unsigned unitFlags = NSCalendarUnitHour | NSCalendarUnitMinute;
// 计算dateComponents,这里也是比较耗时的
NSDateComponents *dateComponents = [calendar components:unitFlags fromDate:date];
BOOL fromResult = (dateComponents.hour > fromHour) || (dateComponents.hour == fromHour && dateComponents.minute >= fromMinute);
BOOL toResult = (dateComponents.hour < toHour) || (dateComponents.hour == toHour && dateComponents.minute <= toMinute);
return toResult && fromResult;
}
效率
indicator_07.png
每个执行3次求平均值
执行次数 | 耗时(us) |
---|---|
1,000 | 1,496 |
10,000 | 11,451 |
100,000 | 82,826 |
1,000,000 | 826,596 |
10,000,000 | 8,341,402 |
使用时间戳特点
方法
目的是计算时间戳是否在某一天的某个区间,所以可以采用对时间戳取余数的方法进行对比。
我们知道一天的时间是24 * 60 * 60,则对应的时间戳对其取余则是在这一天的某一时刻。
当天的时间00:00:00~23:59:59对应的时间戳为0~86399,则余数也应该在这个范围。
所以我们可以利用这个区间去判断指定时间戳是否在这个区间。如下图所示:
indicator_05.png
代码
#define DAY_UNIT (86400)
#define DAY_GMT0_08_00 (28800) // GMT8 16:00
#define DAY_GMT0_13_30 (48600) // GMT8 21:30
- (BOOL)timeStamp:(uint32_t)timeStamp betweenFromHour:(NSInteger)fromHour fromMinute:(NSInteger)fromMinute toHour:(NSInteger)toHour toMinute:(NSInteger)toMinute {
int reminder = timeStamp % DAY_UNIT;
return reminder >= DAY_GMT0_08_00 && reminder <= DAY_GMT0_13_30;
}
效率
执行次数 | 耗时(us) |
---|---|
1,000 | 12 |
10,000 | 100 |
100,000 | 882 |
1,000,000 | 6,822 |
10,000,000 | 71,616 |
结论
对比
indicator_06.png
可看出来,对于执行次数优化非常明显,基本都是99%以上。
分析
根据优化效果,以后如果有关于日历方面的计算,建议思考一下是否需要考虑性能问题。