@@ -1276,49 +1276,94 @@ open class NSDateComponents : NSObject, NSCopying, NSSecureCoding {
1276
1276
public override init ( ) {
1277
1277
super. init ( )
1278
1278
}
1279
-
1279
+
1280
1280
open override var hash : Int {
1281
- var calHash = 0
1282
- if let cal = calendar {
1283
- calHash = cal. hashValue
1284
- }
1285
- if let tz = timeZone {
1286
- calHash ^= tz. hashValue
1287
- }
1288
- var y = year
1289
- if NSDateComponentUndefined == y {
1290
- y = 0
1291
- }
1292
- var m = month
1293
- if NSDateComponentUndefined == m {
1294
- m = 0
1295
- }
1296
- var d = day
1297
- if NSDateComponentUndefined == d {
1298
- d = 0
1299
- }
1300
- var h = hour
1301
- if NSDateComponentUndefined == h {
1302
- h = 0
1303
- }
1304
- var mm = minute
1305
- if NSDateComponentUndefined == mm {
1306
- mm = 0
1307
- }
1308
- var s = second
1309
- if NSDateComponentUndefined == s {
1310
- s = 0
1311
- }
1312
- var yy = yearForWeekOfYear
1313
- if NSDateComponentUndefined == yy {
1314
- yy = 0
1315
- }
1316
- return calHash + ( 32832013 * ( y + yy) + 2678437 * m + 86413 * d + 3607 * h + 61 * mm + s) + ( 41 * weekOfYear + 11 * weekOfMonth + 7 * weekday + 3 * weekdayOrdinal + quarter) * ( 1 << 5 )
1281
+ var hasher = Hasher ( )
1282
+ var mask = 0
1283
+ // The list of fields fed to the hasher here must be exactly
1284
+ // the same as the ones compared in isEqual(_:) (modulo
1285
+ // ordering).
1286
+ //
1287
+ // Given that NSDateComponents instances usually only have a
1288
+ // few fields present, it makes sense to only hash those, as
1289
+ // an optimization. We keep track of the fields hashed in the
1290
+ // mask value, which we also feed to the hasher to make sure
1291
+ // any two unequal values produce different hash encodings.
1292
+ //
1293
+ // FIXME: Why not just feed _values, calendar & timeZone to
1294
+ // the hasher?
1295
+ if let calendar = calendar {
1296
+ hasher. combine ( calendar)
1297
+ mask |= 1 << 0
1298
+ }
1299
+ if let timeZone = timeZone {
1300
+ hasher. combine ( timeZone)
1301
+ mask |= 1 << 1
1302
+ }
1303
+ if era != NSDateComponentUndefined {
1304
+ hasher. combine ( era)
1305
+ mask |= 1 << 2
1306
+ }
1307
+ if year != NSDateComponentUndefined {
1308
+ hasher. combine ( year)
1309
+ mask |= 1 << 3
1310
+ }
1311
+ if quarter != NSDateComponentUndefined {
1312
+ hasher. combine ( quarter)
1313
+ mask |= 1 << 4
1314
+ }
1315
+ if month != NSDateComponentUndefined {
1316
+ hasher. combine ( month)
1317
+ mask |= 1 << 5
1318
+ }
1319
+ if day != NSDateComponentUndefined {
1320
+ hasher. combine ( day)
1321
+ mask |= 1 << 6
1322
+ }
1323
+ if hour != NSDateComponentUndefined {
1324
+ hasher. combine ( hour)
1325
+ mask |= 1 << 7
1326
+ }
1327
+ if minute != NSDateComponentUndefined {
1328
+ hasher. combine ( minute)
1329
+ mask |= 1 << 8
1330
+ }
1331
+ if second != NSDateComponentUndefined {
1332
+ hasher. combine ( second)
1333
+ mask |= 1 << 9
1334
+ }
1335
+ if nanosecond != NSDateComponentUndefined {
1336
+ hasher. combine ( nanosecond)
1337
+ mask |= 1 << 10
1338
+ }
1339
+ if weekOfYear != NSDateComponentUndefined {
1340
+ hasher. combine ( weekOfYear)
1341
+ mask |= 1 << 11
1342
+ }
1343
+ if weekOfMonth != NSDateComponentUndefined {
1344
+ hasher. combine ( weekOfMonth)
1345
+ mask |= 1 << 12
1346
+ }
1347
+ if yearForWeekOfYear != NSDateComponentUndefined {
1348
+ hasher. combine ( yearForWeekOfYear)
1349
+ mask |= 1 << 13
1350
+ }
1351
+ if weekday != NSDateComponentUndefined {
1352
+ hasher. combine ( weekday)
1353
+ mask |= 1 << 14
1354
+ }
1355
+ if weekdayOrdinal != NSDateComponentUndefined {
1356
+ hasher. combine ( weekdayOrdinal)
1357
+ mask |= 1 << 15
1358
+ }
1359
+ hasher. combine ( isLeapMonth)
1360
+ hasher. combine ( mask)
1361
+ return hasher. finalize ( )
1317
1362
}
1318
-
1363
+
1319
1364
open override func isEqual( _ object: Any ? ) -> Bool {
1320
1365
guard let other = object as? NSDateComponents else { return false }
1321
-
1366
+ // FIXME: Why not just compare _values, calendar & timeZone?
1322
1367
return self === other
1323
1368
|| ( era == other. era
1324
1369
&& year == other. year
0 commit comments