【问题标题】:Simplest way to loop between two NSDates on iPhone?在 iPhone 上的两个 NSDate 之间循环的最简单方法?
【发布时间】:2011-03-22 09:33:39
【问题描述】:

从一个日期循环到另一个日期的最简单方法是什么?

我想要的概念是这样的:

for (NSDate *date = [[startDate copy] autorelease]; [date compare: endDate] < 0;
     date = [date dateByAddingDays: 1]) {
    // do stuff here
}

这当然行不通:没有dateByAddingDays:。即使这样做了,也会留下一大堆自动释放的对象等待销毁。

这是我的想法:

  • 我不能只添加NSTimeInterval,因为一天中的秒数可能会有所不同。
  • 我可以把它分解成NSDateComponents 并在组件上加一天,然后重新组装它。但那是又长又丑的代码。

所以我希望有人为此尝试了一些选项,并找到了一个好的选项。有什么想法吗?

【问题讨论】:

  • 嗯,关键是没有 dateByAddingDays。 :)

标签: cocoa-touch nsdate foundation


【解决方案1】:

设置一个 oneDay 日期组件常量并重复添加:

    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *oneDay = [[NSDateComponents alloc] init];
    [oneDay setDay: 1];

    for (id date = [[startDate copy] autorelease]; [date compare: endDate] <= 0;
        date = [calendar dateByAddingComponents: oneDay
                                         toDate: date
                                        options: 0] ) {
        NSLog( @"%@ in [%@,%@]", date, startDate, endDate );
    }

这仍然会留下自动释放对象的痕迹,但 dateByAddingComponents:toDate:options: 负责。不确定对此有什么可做的。

【讨论】:

    【解决方案2】:

    向 DateRange 类添加快速枚举:

    - (NSUInteger)countByEnumeratingWithState: (NSFastEnumerationState *)state
                                      objects: (id *)stackbuf
                                        count: (NSUInteger)len;
    {
        NSInteger days = 0;
        id current = nil;
        id components = nil;
        if (state->state == 0)
        {
            current = [NSCalendar currentCalendar];
            state->mutationsPtr = &state->extra[0];
            components = [current components: NSDayCalendarUnit
                                    fromDate: startDate
                                      toDate: endDate
                                     options: 0];
            days = [components day];
            state->extra[0] = days;
            state->extra[1] = (uintptr_t)current;
            state->extra[2] = (uintptr_t)components;
        } else {
            days = state->extra[0];
            current = (NSCalendar *)(state->extra[1]);
            components = (NSDateComponents *)(state->extra[2]);
        }
        NSUInteger count = 0;
        if (state->state <= days) {
            state->itemsPtr = stackbuf;
            while ( (state->state <= days) && (count < len) ) {
                [components setDay: state->state];
                stackbuf[count] = [current dateByAddingComponents: components
                                                           toDate: startDate
                                                          options: 0];
                state->state++;
                count++;
            }
        }
        return count;
    }
    

    这很丑陋,但丑陋仅限于我的日期范围类。我的客户端代码只是:

    for (id date in dateRange) {
        NSLog( @"%@ in [%@,%@]", date, startDate, endDate );
    }
    

    如果您还没有 DateRange 类,我认为这可能是创建 DateRange 类的充分理由。

    【讨论】:

      【解决方案3】:

      使用 date = [date dateByAddingTimeInterval:24 * 60 * 60] 怎么样?

      for (NSDate *date = [[startDate copy] autorelease]; [date compare: endDate] < 0;
       date = [date dateByAddingTimeInterval:24 * 60 * 60] ) {
          NSLog( @"%@ in [%@,%@]", date, startDate, endDate );
      }
      

      【讨论】:

      • 这是一个好的开始,但在大多数时区,由于夏令时,每年有几天的小时数不同。如果我的时间接近午夜,这可能会有所作为。例如,上午 12:05 可能在同一天变成晚上 11:05。周日晚上 11:05 可能会变成周二凌晨 1:05。
      猜你喜欢
      • 1970-01-01
      • 2013-08-19
      • 2011-09-14
      • 2010-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多