我试图测试我的一种方法可以正确地比较两次。它工作正常,除非我在我的组件中添加一个时区,如下所示:
_calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.second = 31;
components.minute = 21;
components.hour = 5;
components.day = 30;
components.month = 3;
components.year = 2016;
components.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
_mar30_2016Morning = [_calendar dateFromComponents:components];
components.second = 01;
components.minute = 00;
components.hour = 22;
components.day = 30;
components.month = 3;
components.year = 2016;
components.timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
_mar30_2016Evening = [_calendar dateFromComponents:components];
//Test two dates are equal
-(void) testCompareWithoutTimeTo
{
XCTAssertEqual([_mar30_2016Morning compareWithoutTimeTo:_mar30_2016Evening],NSOrderedSame);
}
首先:
-(NSComparisonResult) compareWithoutTimeTo:(NSDate *) otherDate {
NSDate *this = [self copy];
NSDate *that = [otherDate copy];
return [[NSCalendar currentCalendar] compareDate:this toDate:that toUnitGranularity:NSCalendarUnitDay];;
}
第二种方式:
NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&this interval:NULL forDate:this];
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&that interval:NULL forDate:that];
NSComparisonResult result = [this compare:that];
这些日期是在同一天,它必须返回相同但它返回它是不同的日子?!
答案 0 :(得分:3)
这很令人困惑,而且没有很好的记录。
@RobMayoff告诉你出了什么问题,但还有进一步的解释。
以下是我对其工作原理的理解。您创建NSDateComponents
并为其指定时区。然后将它们转换为NSDates,它会丢弃时区信息,并将这些日期表示为iOS纪元时间的偏移量,总是以UTC格式表示。 (NSDate
个对象没有时区它们代表地球上任何时间的瞬间。)
最后,您要求日历对象比较2个日期。日历对象在进行比较之前将提供的日期转换为其时区。如果2个日期落在日历当前时区的不同日期,那么您将获得不平等的日期。
解决方案是在进行比较之前创建日历并将其时区设置为UTC。
只需在您发布的代码中添加第二行:
_calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
_calendar.timeZone = [NSTimeZone timeZoneWithName:@"UTC"]; //This is the fix
正如rmaddy在评论中指出的那样,没有要求你比较UTC中的日期。您只需要确保创建日期并使用相同的时区进行比较。由于您使用时区为UTC的NSDateComponents创建输入日期,因此需要将它们与也设置为UTC的日历进行比较。
答案 1 :(得分:1)
您没有设置日历的时区,因此它使用的是设备的时区设置,可能不是UTC。这两个NSDate
值落在许多时区的不同日历日。