Skip to content

Commit 28eaab4

Browse files
Kieran Farrellnaotoj
authored andcommitted
8369184: SimpleTimeZone equals() Returns True for Unequal Instances with Different hashCode Values
Backport-of: 37b725d9c12834358a562e6c03fb7f566d639ca5
1 parent b8aa130 commit 28eaab4

File tree

2 files changed

+102
-8
lines changed

2 files changed

+102
-8
lines changed

src/java.base/share/classes/java/util/SimpleTimeZone.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -112,15 +112,15 @@
112112
* <pre><code>
113113
* // Base GMT offset: -8:00
114114
* // DST starts: at 2:00am in standard time
115-
* // on the first Sunday in April
115+
* // on the second Sunday in March
116116
* // DST ends: at 2:00am in daylight time
117-
* // on the last Sunday in October
117+
* // on the first Sunday in November
118118
* // Save: 1 hour
119119
* SimpleTimeZone(-28800000,
120120
* "America/Los_Angeles",
121-
* Calendar.APRIL, 1, -Calendar.SUNDAY,
121+
* Calendar.MARCH, 8, -Calendar.SUNDAY,
122122
* 7200000,
123-
* Calendar.OCTOBER, -1, Calendar.SUNDAY,
123+
* Calendar.NOVEMBER, 1, -Calendar.SUNDAY,
124124
* 7200000,
125125
* 3600000)
126126
*
@@ -863,13 +863,24 @@ public Object clone()
863863
}
864864

865865
/**
866-
* Generates the hash code for the SimpleDateFormat object.
866+
* Generates the hash code for the SimpleTimeZone object.
867867
* @return the hash code for this object
868868
*/
869869
public int hashCode()
870870
{
871-
return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
872-
endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
871+
int hash = 31 * getID().hashCode() + rawOffset;
872+
hash = 31 * hash + Boolean.hashCode(useDaylight);
873+
if (useDaylight) {
874+
hash = 31 * hash + startMonth;
875+
hash = 31 * hash + startDay;
876+
hash = 31 * hash + startDayOfWeek;
877+
hash = 31 * hash + startTime;
878+
hash = 31 * hash + endMonth;
879+
hash = 31 * hash + endDay;
880+
hash = 31 * hash + endDayOfWeek;
881+
hash = 31 * hash + endTime;
882+
}
883+
return hash;
873884
}
874885

875886
/**
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8369184
27+
* @summary Checks if equals()/hashCode() of SimpleTimeZone works correctly
28+
* @run junit SimpleTimeZoneEqualsHashCodeTest
29+
*/
30+
31+
import java.util.SimpleTimeZone;
32+
import static java.util.Calendar.MARCH;
33+
import static java.util.Calendar.NOVEMBER;
34+
import static java.util.Calendar.SUNDAY;
35+
36+
import org.junit.jupiter.api.Test;
37+
38+
import static org.junit.jupiter.api.Assertions.assertEquals;
39+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
40+
import static org.junit.jupiter.api.Assertions.assertTrue;
41+
42+
public class SimpleTimeZoneEqualsHashCodeTest {
43+
private static final SimpleTimeZone STZ_WITH_DST =
44+
new SimpleTimeZone(-288_000_000, "America/Los_Angeles",
45+
MARCH, 8, -SUNDAY, 7_200_000,
46+
NOVEMBER, 1, -SUNDAY, 7_200_000);
47+
private static final SimpleTimeZone STZ_WITHOUT_DST =
48+
new SimpleTimeZone(0, "foo");
49+
50+
@Test
51+
void withDSTTest() {
52+
var stz = (SimpleTimeZone)STZ_WITH_DST.clone();
53+
assertEquals(STZ_WITH_DST, stz);
54+
assertEquals(STZ_WITH_DST.hashCode(), stz.hashCode());
55+
56+
stz.setEndRule(NOVEMBER, 8, -SUNDAY, 7_200_000);
57+
assertNotEquals(STZ_WITH_DST, stz);
58+
// From the contract point, hash codes may be the same.
59+
// This tests the implementation which considers DST
60+
// related fields for calculating the hash code.
61+
assertNotEquals(STZ_WITH_DST.hashCode(), stz.hashCode());
62+
}
63+
64+
@Test
65+
void withoutDSTTest() {
66+
var stz = (SimpleTimeZone)STZ_WITHOUT_DST.clone();
67+
68+
// Only setting start rule. Still considered non-DST zone
69+
stz.setStartRule(MARCH, 8, -SUNDAY, 7_200_000);
70+
assertTrue(!stz.useDaylightTime());
71+
assertEquals(STZ_WITHOUT_DST, stz);
72+
assertEquals(STZ_WITHOUT_DST.hashCode(), stz.hashCode());
73+
74+
// Setting end rule as well. Now it is considered DST zone
75+
stz.setEndRule(NOVEMBER, 8, -SUNDAY, 7_200_000);
76+
assertTrue(stz.useDaylightTime());
77+
assertNotEquals(STZ_WITHOUT_DST, stz);
78+
// From the contract point, hash codes may be the same.
79+
// This tests the implementation which considers DST
80+
// related fields for calculating the hash code.
81+
assertNotEquals(STZ_WITHOUT_DST.hashCode(), stz.hashCode());
82+
}
83+
}

0 commit comments

Comments
 (0)