NSPredicate两个日期之间的范围没有按预期工作

时间:2013-10-04 01:31:42

标签: iphone ios objective-c ipad nspredicate

我有两个NSDate s:

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];

但即使谓词的第二部分专门使用<=,它也会将对象返回到前一天(即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设置为第二天?

由于

2 个答案:

答案 0 :(得分:6)

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

有两种常见的解决方法:

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

以下是使用第一种方法的方法:

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

答案 1 :(得分: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];