4

我有这两个NSDates:

NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"MM/dd/yyyy"];
NSDate *rangeStart = [df dateFromString: @"03/03/2013"];
NSDate *rangeEnd = [df dateFromString: @"10/04/2013"];

而这个谓词:

request.predicate = [NSPredicate predicateWithFormat:@"createdDate >= %@ AND createdDate <= %@", rangeStart, rangeEnd];

但是,即使谓词的第二部分专门使用 a <=,它也会返回直到前一天(即10/03/2013)的对象。

我也尝试像这样构造谓词:

NSPredicate *dateStartPredicate = [NSPredicate predicateWithFormat:@"createdDate >= %@", rangeStart];
NSPredicate *dateEndPredicate = [NSPredicate predicateWithFormat:@"createdDate <= %@", rangeEnd];
NSPredicate *finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:dateStartPredicate, dateEndPredicate, nil]]; 

但我得到了相同的结果。难道我做错了什么?这实际上是预期的行为吗?如果是,怎么能设置rangeEnd到第二天呢?

谢谢

4

2 回答 2

7

NSDate对象也包括时间。当您将一个没有时间的日期传递给该dateFromString:方法时,将假定相应日期的午夜,即只有在午夜发生的项目才会true以小于或等于表达式返回。

有两种常见的解决方法:

  • 将一天添加到rangeEnd,并使用“小于”而不是“小于或等于”,或
  • 将时间添加到rangeEnd日期(这并不理想,因为您要么需要在长字符串中指定时间,要么会错过当天最后一秒发生的项目)。

以下是如何使用第一种方法:

request.predicate = [NSPredicate
    predicateWithFormat:@"createdDate >= %@ AND createdDate < %@"
    , rangeStart
    , [rangeEnd dateByAddingTimeInterval:60*60*24]
];
于 2013-10-04T01:44:20.820 回答
2

请记住,即使类的名称是 NSDate,这些对象也代表特定的时间点(而不是一整天)。 rangeEnd设置为 10 月 4 日午夜。由于午夜是当天的第一个时刻,因此只有当天午夜的事件才会包含在您的结果中。如下图所示移至rangeEnd第二天,您应该会得到预期的结果。

NSCalendar* calendar = [NSCalendar autoupdatingCurrentCalendar];
NSDateComponents* components = [[NSDateComponents alloc] init];
components.day = 1;
NSDate* newDate = [calendar dateByAddingComponents:components toDate:rangeEnd options: 0];
于 2013-10-04T01:44:40.110 回答