24
24
package test .java .time .zone ;
25
25
26
26
import java .time .DayOfWeek ;
27
+ import java .time .Duration ;
27
28
import java .time .Instant ;
28
29
import java .time .LocalDate ;
29
30
import java .time .LocalDateTime ;
37
38
import java .time .zone .ZoneOffsetTransitionRule ;
38
39
import java .time .zone .ZoneRules ;
39
40
import java .util .Collections ;
41
+ import java .util .List ;
40
42
41
- import org .testng .annotations .Test ;
42
43
import org .testng .annotations .DataProvider ;
44
+ import org .testng .annotations .Test ;
43
45
import static org .testng .Assert .assertEquals ;
44
46
import static org .testng .Assert .assertTrue ;
45
47
46
48
/**
47
49
* @summary Tests for ZoneRules class.
48
50
*
49
- * @bug 8212970 8236903
51
+ * @bug 8212970 8236903 8239836
50
52
*/
51
53
@ Test
52
54
public class TestZoneRules {
@@ -59,37 +61,44 @@ public class TestZoneRules {
59
61
private static final ZoneId TOKYO = ZoneId .of ("Asia/Tokyo" );
60
62
private static final LocalTime ONE_AM = LocalTime .of (1 , 0 );
61
63
64
+ private static final ZoneOffset OFF_0 = ZoneOffset .ofHours (0 );
65
+ private static final ZoneOffset OFF_1 = ZoneOffset .ofHours (1 );
66
+ private static final ZoneOffset OFF_2 = ZoneOffset .ofHours (2 );
67
+ private static final List EL = Collections .emptyList ();
68
+ private static final ZoneOffsetTransition ZOT = ZoneId .of ("America/Los_Angeles" ).getRules ().getTransitions ().get (0 );
69
+ private static final ZoneOffsetTransitionRule ZOTR = ZoneId .of ("America/Los_Angeles" ).getRules ().getTransitionRules ().get (0 );
70
+
62
71
@ DataProvider
63
72
private Object [][] negativeDST () {
64
73
return new Object [][] {
65
74
// ZoneId, localDate, offset, standard offset, isDaylightSavings
66
75
// Europe/Dublin for the Rule "Eire"
67
- {DUBLIN , LocalDate .of (1970 , 6 , 23 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
68
- {DUBLIN , LocalDate .of (1971 , 6 , 23 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
69
- {DUBLIN , LocalDate .of (1971 , 11 , 1 ), ZoneOffset . ofHours ( 0 ), ZoneOffset . ofHours ( 0 ) , false },
70
- {DUBLIN , LocalDate .of (2019 , 6 , 23 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
71
- {DUBLIN , LocalDate .of (2019 , 12 , 23 ), ZoneOffset . ofHours ( 0 ), ZoneOffset . ofHours ( 0 ) , false },
76
+ {DUBLIN , LocalDate .of (1970 , 6 , 23 ), OFF_1 , OFF_0 , true },
77
+ {DUBLIN , LocalDate .of (1971 , 6 , 23 ), OFF_1 , OFF_0 , true },
78
+ {DUBLIN , LocalDate .of (1971 , 11 , 1 ), OFF_0 , OFF_0 , false },
79
+ {DUBLIN , LocalDate .of (2019 , 6 , 23 ), OFF_1 , OFF_0 , true },
80
+ {DUBLIN , LocalDate .of (2019 , 12 , 23 ), OFF_0 , OFF_0 , false },
72
81
73
82
// Europe/Prague which contains fixed negative savings (not a named Rule)
74
- {PRAGUE , LocalDate .of (1946 , 9 , 30 ), ZoneOffset . ofHours ( 2 ), ZoneOffset . ofHours ( 1 ) , true },
75
- {PRAGUE , LocalDate .of (1946 , 10 , 10 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 1 ) , false },
76
- {PRAGUE , LocalDate .of (1946 , 12 , 3 ), ZoneOffset . ofHours ( 0 ), ZoneOffset . ofHours ( 0 ) , false },
77
- {PRAGUE , LocalDate .of (1947 , 2 , 25 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 1 ) , false },
78
- {PRAGUE , LocalDate .of (1947 , 4 , 30 ), ZoneOffset . ofHours ( 2 ), ZoneOffset . ofHours ( 1 ) , true },
83
+ {PRAGUE , LocalDate .of (1946 , 9 , 30 ), OFF_2 , OFF_1 , true },
84
+ {PRAGUE , LocalDate .of (1946 , 10 , 10 ), OFF_1 , OFF_1 , false },
85
+ {PRAGUE , LocalDate .of (1946 , 12 , 3 ), OFF_0 , OFF_0 , false },
86
+ {PRAGUE , LocalDate .of (1947 , 2 , 25 ), OFF_1 , OFF_1 , false },
87
+ {PRAGUE , LocalDate .of (1947 , 4 , 30 ), OFF_2 , OFF_1 , true },
79
88
80
89
// Africa/Windhoek for the Rule "Namibia"
81
- {WINDHOEK , LocalDate .of (1994 , 3 , 23 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 1 ) , false },
82
- {WINDHOEK , LocalDate .of (2016 , 9 , 23 ), ZoneOffset . ofHours ( 2 ), ZoneOffset . ofHours ( 1 ) , true },
90
+ {WINDHOEK , LocalDate .of (1994 , 3 , 23 ), OFF_1 , OFF_1 , false },
91
+ {WINDHOEK , LocalDate .of (2016 , 9 , 23 ), OFF_2 , OFF_1 , true },
83
92
84
93
// Africa/Casablanca for the Rule "Morocco" Defines negative DST till 2037 as of 2019a.
85
- {CASABLANCA , LocalDate .of (1939 , 9 , 13 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
86
- {CASABLANCA , LocalDate .of (1939 , 11 , 20 ), ZoneOffset . ofHours ( 0 ), ZoneOffset . ofHours ( 0 ) , false },
87
- {CASABLANCA , LocalDate .of (2018 , 6 , 18 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
88
- {CASABLANCA , LocalDate .of (2019 , 1 , 1 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
89
- {CASABLANCA , LocalDate .of (2019 , 5 , 6 ), ZoneOffset . ofHours ( 0 ), ZoneOffset . ofHours ( 0 ) , false },
90
- {CASABLANCA , LocalDate .of (2037 , 10 , 5 ), ZoneOffset . ofHours ( 0 ), ZoneOffset . ofHours ( 0 ) , false },
91
- {CASABLANCA , LocalDate .of (2037 , 11 , 16 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
92
- {CASABLANCA , LocalDate .of (2038 , 11 , 1 ), ZoneOffset . ofHours ( 1 ), ZoneOffset . ofHours ( 0 ) , true },
94
+ {CASABLANCA , LocalDate .of (1939 , 9 , 13 ), OFF_1 , OFF_0 , true },
95
+ {CASABLANCA , LocalDate .of (1939 , 11 , 20 ), OFF_0 , OFF_0 , false },
96
+ {CASABLANCA , LocalDate .of (2018 , 6 , 18 ), OFF_1 , OFF_0 , true },
97
+ {CASABLANCA , LocalDate .of (2019 , 1 , 1 ), OFF_1 , OFF_0 , true },
98
+ {CASABLANCA , LocalDate .of (2019 , 5 , 6 ), OFF_0 , OFF_0 , false },
99
+ {CASABLANCA , LocalDate .of (2037 , 10 , 5 ), OFF_0 , OFF_0 , false },
100
+ {CASABLANCA , LocalDate .of (2037 , 11 , 16 ), OFF_1 , OFF_0 , true },
101
+ {CASABLANCA , LocalDate .of (2038 , 11 , 1 ), OFF_1 , OFF_0 , true },
93
102
};
94
103
}
95
104
@@ -108,6 +117,28 @@ private Object[][] transitionBeyondDay() {
108
117
};
109
118
}
110
119
120
+ @ DataProvider
121
+ private Object [][] emptyTransitionList () {
122
+ return new Object [][] {
123
+ // days, offset, std offset, savings, isDST
124
+ {7 , 1 , 2 , -1 , true },
125
+ {-7 , 1 , 1 , 0 , false },
126
+ };
127
+ }
128
+
129
+ @ DataProvider
130
+ private Object [][] isFixedOffset () {
131
+ return new Object [][] {
132
+ // ZoneRules, expected
133
+ {ZoneRules .of (OFF_0 ), true },
134
+ {ZoneRules .of (OFF_0 , OFF_0 , EL , EL , EL ), true },
135
+ {ZoneRules .of (OFF_0 , OFF_1 , EL , EL , EL ), false },
136
+ {ZoneRules .of (OFF_0 , OFF_0 , Collections .singletonList (ZOT ), EL , EL ), false },
137
+ {ZoneRules .of (OFF_0 , OFF_0 , EL , Collections .singletonList (ZOT ), EL ), false },
138
+ {ZoneRules .of (OFF_0 , OFF_0 , EL , EL , Collections .singletonList (ZOTR )), false },
139
+ };
140
+ }
141
+
111
142
/**
112
143
* Test ZoneRules whether the savings are positive in time zones that have
113
144
* negative savings in the source TZ files.
@@ -147,28 +178,57 @@ public void test_TransitionLastRuleYear() {
147
178
59 ,
148
179
59 ,
149
180
999999999 ).toInstant (ZoneOffset .UTC );
150
- ZoneOffset offsetZero = ZoneOffset .ofHours (0 );
151
- ZoneOffset offsetPlusOneHour = ZoneOffset .ofHours (1 );
152
- ZoneRules zoneRulesA = ZoneRules .of (offsetPlusOneHour );
153
- ZoneOffsetTransition transition = ZoneOffsetTransition .of (LocalDateTime .ofEpochSecond (0 , 0 , offsetZero ),
154
- offsetZero ,
155
- offsetPlusOneHour );
181
+ ZoneRules zoneRulesA = ZoneRules .of (OFF_1 );
182
+ ZoneOffsetTransition transition = ZoneOffsetTransition .of (LocalDateTime .ofEpochSecond (0 , 0 , OFF_0 ),
183
+ OFF_0 ,
184
+ OFF_1 );
156
185
ZoneOffsetTransitionRule transitionRule = ZoneOffsetTransitionRule .of (Month .JANUARY ,
157
186
1 ,
158
187
DayOfWeek .SUNDAY ,
159
188
LocalTime .MIDNIGHT ,
160
189
true ,
161
190
ZoneOffsetTransitionRule .TimeDefinition .STANDARD ,
162
- offsetZero ,
163
- offsetZero ,
164
- offsetPlusOneHour );
165
- ZoneRules zoneRulesB = ZoneRules .of (offsetZero ,
166
- offsetZero ,
191
+ OFF_0 ,
192
+ OFF_0 ,
193
+ OFF_1 );
194
+ ZoneRules zoneRulesB = ZoneRules .of (OFF_0 ,
195
+ OFF_0 ,
167
196
Collections .singletonList (transition ),
168
197
Collections .singletonList (transition ),
169
198
Collections .singletonList (transitionRule ));
170
199
ZoneOffset offsetA = zoneRulesA .getOffset (maxLocalDateTime );
171
200
ZoneOffset offsetB = zoneRulesB .getOffset (maxLocalDateTime );
172
201
assertEquals (offsetA , offsetB );
173
202
}
203
+
204
+ /**
205
+ * Tests whether empty "transitionList" is correctly interpreted.
206
+ * @bug 8239836
207
+ */
208
+ @ Test (dataProvider ="emptyTransitionList" )
209
+ public void test_EmptyTransitionList (int days , int offset , int stdOffset , int savings , boolean isDST ) {
210
+ LocalDateTime transitionDay = LocalDateTime .of (2020 , 1 , 1 , 2 , 0 );
211
+ Instant testDay = transitionDay .plusDays (days ).toInstant (ZoneOffset .UTC );
212
+ ZoneOffsetTransition trans = ZoneOffsetTransition .of (
213
+ transitionDay ,
214
+ OFF_1 ,
215
+ OFF_2 );
216
+ ZoneRules rules = ZoneRules .of (OFF_1 , OFF_1 ,
217
+ Collections .singletonList (trans ),
218
+ Collections .emptyList (), Collections .emptyList ());
219
+
220
+ assertEquals (rules .getOffset (testDay ), ZoneOffset .ofHours (offset ));
221
+ assertEquals (rules .getStandardOffset (testDay ), ZoneOffset .ofHours (stdOffset ));
222
+ assertEquals (rules .getDaylightSavings (testDay ), Duration .ofHours (savings ));
223
+ assertEquals (rules .isDaylightSavings (testDay ), isDST );
224
+ }
225
+
226
+ /**
227
+ * Tests whether isFixedOffset() is working correctly
228
+ * @bug 8239836
229
+ */
230
+ @ Test (dataProvider ="isFixedOffset" )
231
+ public void test_IsFixedOffset (ZoneRules zr , boolean expected ) {
232
+ assertEquals (zr .isFixedOffset (), expected );
233
+ }
174
234
}
0 commit comments