I have a problem with the implementations of isEqual: and hash in
NSDate.
Let's say we have two dates:
NSDate *a, *b;
// This is actually a common case if you are doing floating point math
to generate dates and get small rounding errors.
a = [NSDate dateWithTimeIntervalSinceReferenceDate:100000.001];
b = [NSDate dateWithTimeIntervalSinceReferenceDate:99999.998];
printf("a = %d, b=%d, equal=%d\n", [a hash] , [b hash], [a isEqual:b]);
// this code will print a = 100000, b = 99999, equal = 1
This breaks the NSDictionary rule that hash of two objects must equal
if they are -isEqual:.
I propose that we change the implementations to this:
- (unsigned) hash
{
return (unsigned)([self timeIntervalSinceReferenceDate]+0.5);
}
- (BOOL) isEqual: (id)other
{
if (other == nil)
return NO;
if ([other isKindOfClass: abstractClass]
&& (int)(otherTime(self)+0.5) == (int)(otherTime(other)+0.5) )
return YES;
return NO;
}
After my change the program's output changes to:
a = 100000, b = 100000, equal = 1
I realize that the dates 100.5 and 100.49 are now not -isEqual:, but
you have to draw the line somewhere, and putting it at .000 as the old
code was worse.