【问题标题】:NSDateComponents Time ProfileNSDateComponents 时间配置文件
【发布时间】:2014-03-05 18:37:47
【问题描述】:

我的问题与下面代码 sn-p 中给出的 NSDateComponents 操作的时间配置文件有关。

  • 我有一个迭代大量 NSDate 对象的方法
  • 该方法的一部分要求我丢弃每个日期的小时、分钟和秒。
  • 为此,我有 3 个步骤:

    1. 我从原始日期创建了一个 NSDateComponents 对象。
    2. 我将 H:M:S 元素设置为 0
    3. 我根据需要将 H:M:S 设置为 0 的新日期对象

问题:

上面的步骤 1 和 3 占用了我整个方法执行时间的很大一部分,分别为 22.4% 和 56.8%。

我正在寻找有关如何优化这部分代码的建议,或者寻找可能表现更好的将 H:M:S 归零的替代方法。

NSDate* date = [[NSDate alloc] init];
// Next line takes 22.4% of the overall method execution time
NSDateComponents* components =  [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit 
                                | NSDayCalendarUnit | NSHourCalendarUnit  
                                | NSSecondCalendarUnit) fromDate:date]; 

[components setHour:0];
[components setMinute:0];
[components setSecond:0];

// Next line takes 56.8% of the overall method execution time
date = [calendar dateFromComponents:components];

【问题讨论】:

  • 如果你想粗暴一点(纯粹主义者会作呕),而且你不介意在 UTC 工作(或多或少),你可以简单地提取 NSTimeInterval,除以秒数在一天中,发言,乘以一天中的秒数,然后转换回 NSDate。如果您愿意,可以在一行(稍长)中完成。
  • UTC 很好。我会在早上实现这个,看看效果如何。
  • 这非常适合将 H:M:S 归零。查看另一个我想保留小时值的用例,我开始得到有趣的结果。不是我问的问题,而是值得注意的观察如果我尝试转换 2014-03-03 01:30:00 我得到 2014-03-03 00:59:44

标签: ios nsdate nsdatecomponents


【解决方案1】:

更新

时钟:

时间 1:≈ 0.000139 - 选项 1 - 原始

时间 2:≈ 0.000108 - 选项 2

时间 3:≈ 0.000013 - 选项 3

时间 4:≈ 0.000004 - 选项 4

选项 1 - 原始

NSDate* originDate = [[NSDate alloc] init];
NSDate* date = [[NSDate alloc] init];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* components =  [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit
                                                      | NSDayCalendarUnit | NSHourCalendarUnit
                                                      | NSSecondCalendarUnit) fromDate:date];

[components setHour:0];
[components setMinute:0];
[components setSecond:0];
date = [calendar dateFromComponents:components];
NSLog(@"Time 1: %f", -[originDate timeIntervalSinceNow]);

选项 2

你不需要

[components setHour:0];
[components setMinute:0];
[components setSecond:0];

甚至不要将这些作为选项添加到日期组​​件

NSDate* originDate2 = [[NSDate alloc] init];
NSDate* date2 = [[NSDate alloc] init];
NSCalendar *calendar2 = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents* components2 =  [calendar2 components:(NSYearCalendarUnit | NSMonthCalendarUnit
                                                        | NSDayCalendarUnit
                                                        ) fromDate:date2];
date2 = [calendar2 dateFromComponents:components2];
NSLog(@"Time 2: %f", -[originDate2 timeIntervalSinceNow]);

来源:Similar Question + David 的评论

选项 3

基本上,我发现如果我使用已经创建的 NSCalendar 运行该方法,我的速度会持续提高 85% 到 90%。

在运行方法之前声明 calendarProperty 并对其进行初始化

NSDate* originDate3 = [[NSDate alloc] init];
NSDate* date3 = [[NSDate alloc] init];
NSDateComponents* components3 =  [calendarProperty components:(NSYearCalendarUnit | NSMonthCalendarUnit
                                                               | NSDayCalendarUnit
                                                               ) fromDate:date3];
date3 = [calendarProperty dateFromComponents:components3];
NSLog(@"Time 3: %f", -[originDate3 timeIntervalSinceNow]);

选项 4

* 基于@HotLicks 的评论 *

同时避免所有烦人的 dateComponents - 大约快 95%

我不确定选项 4 在实践中的一致性如何,但它的速度最快,而且到目前为止对我来说是可靠的。

NSDate* originDate4 = [[NSDate alloc] init];
NSDate* date4 = [[NSDate alloc] init];
float date4Interval = [date4 timeIntervalSince1970];
int totalDays = date4Interval / (60 * 60 * 24);
date4 = [NSDate dateWithTimeIntervalSince1970:totalDays * 60 * 60 * 24];
NSLog(@"Time 4: %f", -[originDate4 timeIntervalSinceNow]);

【讨论】:

  • 啊!不包括组件,好点,。与我的整体方法相比,我仍然担心从组件中获取日期对象的相对成本。目前是一个瓶颈。我会在早上再分析一下。
  • 我想我找到了一种通过提前初始化日历来获得显着更快结果的方法。让我知道它是否也适用于您!
  • 重用 NSCalendar 实例是我可以做的,所以这不是瓶颈的一部分。查看您拥有的时序配置文件很有趣。我希望他们在我身边被复制。很快就会发现!
  • 是的,我不确定以这种方式计时是否是最佳做法,但我认为它可以很好地估计。
  • 我已将此标记为答案,即基于@HotLicks 评论的选项 4。请注意我上面的评论,当调整此方法以保持小时值时,结果会略有偏差。为了保持小时值,我初始化了我的 NSDateComponents 并将 Hour*60 添加到最终的 NSDateInterval 中,然后再转换回日期。这摆脱了 [calendar dateFromComponents:components] 调用,这是一个大猪。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
  • 2019-06-22
  • 2014-05-14
  • 1970-01-01
  • 2013-02-16
  • 1970-01-01
相关资源
最近更新 更多