Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/util/calendar/zi/Zoneinfo.java
38855 views
1
/*
2
* Copyright (c) 2000, 2013, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
import java.io.BufferedReader;
27
import java.io.FileReader;
28
import java.io.FileNotFoundException;
29
import java.io.IOException;
30
import java.util.HashMap;
31
import java.util.List;
32
import java.util.Map;
33
import java.util.StringTokenizer;
34
35
/**
36
* Zoneinfo provides javazic compiler front-end functionality.
37
* @since 1.4
38
*/
39
class Zoneinfo {
40
41
private static final int minYear = 1900;
42
private static final int maxYear = 2037;
43
private static final long minTime = Time.getLocalTime(minYear, Month.JANUARY, 1, 0);
44
private static int startYear = minYear;
45
private static int endYear = maxYear;
46
47
/**
48
* True if javazic should generate a list of SimpleTimeZone
49
* instances for the SimpleTimeZone-based time zone support.
50
*/
51
static boolean isYearForTimeZoneDataSpecified = false;
52
53
/**
54
* Zone name to Zone mappings
55
*/
56
private Map<String,Zone> zones;
57
58
/**
59
* Rule name to Rule mappings
60
*/
61
private Map<String,Rule> rules;
62
63
/**
64
* Alias name to real name mappings
65
*/
66
private Map<String,String> aliases;
67
68
/**
69
* Constracts a Zoneinfo.
70
*/
71
Zoneinfo() {
72
zones = new HashMap<String,Zone>();
73
rules = new HashMap<String,Rule>();
74
aliases = new HashMap<String,String>();
75
}
76
77
/**
78
* Adds the given zone to the list of Zones.
79
* @param zone Zone to be added to the list.
80
*/
81
void add(Zone zone) {
82
String name = zone.getName();
83
zones.put(name, zone);
84
}
85
86
/**
87
* Adds the given rule to the list of Rules.
88
* @param rule Rule to be added to the list.
89
*/
90
void add(Rule rule) {
91
String name = rule.getName();
92
rules.put(name, rule);
93
}
94
95
/**
96
* Puts the specifid name pair to the alias table.
97
* @param name1 an alias time zone name
98
* @param name2 the real time zone of the alias name
99
*/
100
void putAlias(String name1, String name2) {
101
aliases.put(name1, name2);
102
}
103
104
/**
105
* Sets the given year for SimpleTimeZone list output.
106
* This method is called when the -S option is specified.
107
* @param year the year for which SimpleTimeZone list should be generated
108
*/
109
static void setYear(int year) {
110
setStartYear(year);
111
setEndYear(year);
112
isYearForTimeZoneDataSpecified = true;
113
}
114
115
/**
116
* Sets the start year.
117
* @param year the start year value
118
* @throws IllegalArgumentException if the specified year value is
119
* smaller than the minimum year or greater than the end year.
120
*/
121
static void setStartYear(int year) {
122
if (year < minYear || year > endYear) {
123
throw new IllegalArgumentException("invalid start year specified: " + year);
124
}
125
startYear = year;
126
}
127
128
/**
129
* @return the start year value
130
*/
131
static int getStartYear() {
132
return startYear;
133
}
134
135
/**
136
* Sets the end year.
137
* @param year the end year value
138
* @throws IllegalArgumentException if the specified year value is
139
* smaller than the start year or greater than the maximum year.
140
*/
141
static void setEndYear(int year) {
142
if (year < startYear || year > maxYear) {
143
throw new IllegalArgumentException();
144
}
145
endYear = year;
146
}
147
148
/**
149
* @return the end year value
150
*/
151
static int getEndYear() {
152
return endYear;
153
}
154
155
/**
156
* @return the minimum year value
157
*/
158
static int getMinYear() {
159
return minYear;
160
}
161
162
/**
163
* @return the maximum year value
164
*/
165
static int getMaxYear() {
166
return maxYear;
167
}
168
169
/**
170
* @return the alias table
171
*/
172
Map<String,String> getAliases() {
173
return aliases;
174
}
175
176
/**
177
* @return the Zone list
178
*/
179
Map<String,Zone> getZones() {
180
return zones;
181
}
182
183
/**
184
* @return a Zone specified by name.
185
* @param name a zone name
186
*/
187
Zone getZone(String name) {
188
return zones.get(name);
189
}
190
191
/**
192
* @return a Rule specified by name.
193
* @param name a rule name
194
*/
195
Rule getRule(String name) {
196
return rules.get(name);
197
}
198
199
private static String line;
200
201
private static int lineNum;
202
203
/**
204
* Parses the specified time zone data file and creates a Zoneinfo
205
* that has all Rules, Zones and Links (aliases) information.
206
* @param fname the time zone data file name
207
* @return a Zoneinfo object
208
*/
209
static Zoneinfo parse(String fname) {
210
BufferedReader in = null;
211
try {
212
FileReader fr = new FileReader(fname);
213
in = new BufferedReader(fr);
214
} catch (FileNotFoundException e) {
215
panic("can't open file: "+fname);
216
}
217
Zoneinfo zi = new Zoneinfo();
218
boolean continued = false;
219
Zone zone = null;
220
String l;
221
lineNum = 0;
222
223
try {
224
while ((line = in.readLine()) != null) {
225
lineNum++;
226
// skip blank and comment lines
227
if (line.length() == 0 || line.charAt(0) == '#') {
228
continue;
229
}
230
231
// trim trailing comments
232
int rindex = line.lastIndexOf('#');
233
if (rindex != -1) {
234
// take the data part of the line
235
l = line.substring(0, rindex);
236
} else {
237
l = line;
238
}
239
240
StringTokenizer tokens = new StringTokenizer(l);
241
if (!tokens.hasMoreTokens()) {
242
continue;
243
}
244
String token = tokens.nextToken();
245
246
if (continued || "Zone".equals(token)) {
247
if (zone == null) {
248
if (!tokens.hasMoreTokens()) {
249
panic("syntax error: zone no more token");
250
}
251
token = tokens.nextToken();
252
// if the zone name is in "GMT+hh" or "GMT-hh"
253
// format, ignore it due to spec conflict.
254
if (token.startsWith("GMT+") || token.startsWith("GMT-")) {
255
continue;
256
}
257
zone = new Zone(token);
258
} else {
259
// no way to push the current token back...
260
tokens = new StringTokenizer(l);
261
}
262
263
ZoneRec zrec = ZoneRec.parse(tokens);
264
zrec.setLine(line);
265
zone.add(zrec);
266
if ((continued = zrec.hasUntil()) == false) {
267
if (Zone.isTargetZone(zone.getName())) {
268
// zone.resolve(zi);
269
zi.add(zone);
270
}
271
zone = null;
272
}
273
} else if ("Rule".equals(token)) {
274
if (!tokens.hasMoreTokens()) {
275
panic("syntax error: rule no more token");
276
}
277
token = tokens.nextToken();
278
Rule rule = zi.getRule(token);
279
if (rule == null) {
280
rule = new Rule(token);
281
zi.add(rule);
282
}
283
RuleRec rrec = RuleRec.parse(tokens);
284
rrec.setLine(line);
285
rule.add(rrec);
286
} else if ("Link".equals(token)) {
287
// Link <newname> <oldname>
288
try {
289
String name1 = tokens.nextToken();
290
String name2 = tokens.nextToken();
291
292
// if the zone name is in "GMT+hh" or "GMT-hh"
293
// format, ignore it due to spec conflict with
294
// custom time zones. Also, ignore "ROC" for
295
// PC-ness.
296
if (name2.startsWith("GMT+") || name2.startsWith("GMT-")
297
|| "ROC".equals(name2)) {
298
continue;
299
}
300
zi.putAlias(name2, name1);
301
} catch (Exception e) {
302
panic("syntax error: no more token for Link");
303
}
304
}
305
}
306
in.close();
307
} catch (IOException ex) {
308
panic("IO error: " + ex.getMessage());
309
}
310
311
return zi;
312
}
313
314
/**
315
* Interprets a zone and constructs a Timezone object that
316
* contains enough information on GMT offsets and DST schedules to
317
* generate a zone info database.
318
*
319
* @param zoneName the zone name for which a Timezone object is
320
* constructed.
321
*
322
* @return a Timezone object that contains all GMT offsets and DST
323
* rules information.
324
*/
325
Timezone phase2(String zoneName) {
326
Timezone tz = new Timezone(zoneName);
327
Zone zone = getZone(zoneName);
328
zone.resolve(this);
329
330
// TODO: merge phase2's for the regular and SimpleTimeZone ones.
331
if (isYearForTimeZoneDataSpecified) {
332
ZoneRec zrec = zone.get(zone.size()-1);
333
tz.setLastZoneRec(zrec);
334
tz.setRawOffset(zrec.getGmtOffset());
335
if (zrec.hasRuleReference()) {
336
/*
337
* This part assumes that the specified year is covered by
338
* the rules referred to by the last zone record.
339
*/
340
List<RuleRec> rrecs = zrec.getRuleRef().getRules(startYear);
341
342
if (rrecs.size() == 2) {
343
// make sure that one is a start rule and the other is
344
// an end rule.
345
RuleRec r0 = rrecs.get(0);
346
RuleRec r1 = rrecs.get(1);
347
if (r0.getSave() == 0 && r1.getSave() > 0) {
348
rrecs.set(0, r1);
349
rrecs.set(1, r0);
350
} else if (!(r0.getSave() > 0 && r1.getSave() == 0)) {
351
rrecs = null;
352
Main.error(zoneName + ": rules for " + startYear + " not found.");
353
}
354
} else {
355
rrecs = null;
356
}
357
if (rrecs != null) {
358
tz.setLastRules(rrecs);
359
}
360
}
361
return tz;
362
}
363
364
int gmtOffset;
365
int year = minYear;
366
int fromYear = year;
367
long fromTime = Time.getLocalTime(startYear,
368
Month.JANUARY,
369
1, 0);
370
371
// take the index 0 for the GMT offset of the last zone record
372
ZoneRec zrec = zone.get(zone.size()-1);
373
tz.getOffsetIndex(zrec.getGmtOffset());
374
375
int lastGmtOffsetValue = -1;
376
ZoneRec prevzrec = null;
377
int currentSave = 0;
378
boolean usedZone;
379
for (int zindex = 0; zindex < zone.size(); zindex++) {
380
zrec = zone.get(zindex);
381
usedZone = false;
382
gmtOffset = zrec.getGmtOffset();
383
int stdOffset = zrec.getDirectSave();
384
385
if (gmtOffset != lastGmtOffsetValue) {
386
tz.setRawOffset(gmtOffset, fromTime);
387
lastGmtOffsetValue = gmtOffset;
388
}
389
// If this is the last zone record, take the last rule info.
390
if (!zrec.hasUntil()) {
391
if (zrec.hasRuleReference()) {
392
tz.setLastRules(zrec.getRuleRef().getLastRules());
393
} else if (stdOffset != 0) {
394
// in case the last rule is all year round DST-only
395
// (Asia/Amman once announced this rule.)
396
tz.setLastDSTSaving(stdOffset);
397
}
398
}
399
if (!zrec.hasRuleReference()) {
400
if (!zrec.hasUntil() || zrec.getUntilTime(stdOffset) >= fromTime) {
401
tz.addTransition(fromTime,
402
tz.getOffsetIndex(gmtOffset+stdOffset),
403
tz.getDstOffsetIndex(stdOffset));
404
usedZone = true;
405
}
406
currentSave = stdOffset;
407
// optimization in case the last rule is fixed.
408
if (!zrec.hasUntil()) {
409
if (tz.getNTransitions() > 0) {
410
if (stdOffset == 0) {
411
tz.setDSTType(Timezone.X_DST);
412
} else {
413
tz.setDSTType(Timezone.LAST_DST);
414
}
415
long time = Time.getLocalTime(maxYear,
416
Month.JANUARY, 1, 0);
417
time -= zrec.getGmtOffset();
418
tz.addTransition(time,
419
tz.getOffsetIndex(gmtOffset+stdOffset),
420
tz.getDstOffsetIndex(stdOffset));
421
tz.addUsedRec(zrec);
422
} else {
423
tz.setDSTType(Timezone.NO_DST);
424
}
425
break;
426
}
427
} else {
428
Rule rule = zrec.getRuleRef();
429
boolean fromTimeUsed = false;
430
currentSave = 0;
431
year_loop:
432
for (year = getMinYear(); year <= endYear; year++) {
433
if (zrec.hasUntil() && year > zrec.getUntilYear()) {
434
break;
435
}
436
List<RuleRec> rules = rule.getRules(year);
437
if (rules.size() > 0) {
438
for (int i = 0; i < rules.size(); i++) {
439
RuleRec rrec = rules.get(i);
440
long transition = rrec.getTransitionTime(year,
441
gmtOffset,
442
currentSave);
443
if (zrec.hasUntil()) {
444
if (transition >= zrec.getUntilTime(currentSave)) {
445
// If the GMT offset changed from the previous one,
446
// record fromTime as a transition.
447
if (!fromTimeUsed && prevzrec != null
448
&& gmtOffset != prevzrec.getGmtOffset()) {
449
tz.addTransition(fromTime,
450
tz.getOffsetIndex(gmtOffset+currentSave),
451
tz.getDstOffsetIndex(currentSave));
452
fromTimeUsed = true; // for consistency
453
}
454
break year_loop;
455
}
456
}
457
458
if (fromTimeUsed == false) {
459
if (fromTime <= transition) {
460
fromTimeUsed = true;
461
462
if (fromTime != minTime) {
463
int prevsave;
464
465
// See if until time in the previous
466
// ZoneRec is the same thing as the
467
// local time in the next rule.
468
// (examples are Asia/Ashkhabad in 1991,
469
// Europe/Riga in 1989)
470
471
if (i > 0) {
472
prevsave = rules.get(i-1).getSave();
473
} else {
474
List<RuleRec> prevrules = rule.getRules(year-1);
475
476
if (prevrules.size() > 0) {
477
prevsave = prevrules.get(prevrules.size()-1).getSave();
478
} else {
479
prevsave = 0;
480
}
481
}
482
483
if (rrec.isSameTransition(prevzrec, prevsave, gmtOffset)) {
484
currentSave = rrec.getSave();
485
tz.addTransition(fromTime,
486
tz.getOffsetIndex(gmtOffset+currentSave),
487
tz.getDstOffsetIndex(currentSave));
488
tz.addUsedRec(rrec);
489
usedZone = true;
490
continue;
491
}
492
if (!prevzrec.hasRuleReference()
493
|| rule != prevzrec.getRuleRef()
494
|| (rule == prevzrec.getRuleRef()
495
&& gmtOffset != prevzrec.getGmtOffset())) {
496
int save = (fromTime == transition) ? rrec.getSave() : currentSave;
497
tz.addTransition(fromTime,
498
tz.getOffsetIndex(gmtOffset+save),
499
tz.getDstOffsetIndex(save));
500
tz.addUsedRec(rrec);
501
usedZone = true;
502
}
503
} else { // fromTime == minTime
504
int save = rrec.getSave();
505
tz.addTransition(minTime,
506
tz.getOffsetIndex(gmtOffset),
507
tz.getDstOffsetIndex(0));
508
509
tz.addTransition(transition,
510
tz.getOffsetIndex(gmtOffset+save),
511
tz.getDstOffsetIndex(save));
512
513
tz.addUsedRec(rrec);
514
usedZone = true;
515
}
516
} else if (year == fromYear && i == rules.size()-1) {
517
int save = rrec.getSave();
518
tz.addTransition(fromTime,
519
tz.getOffsetIndex(gmtOffset+save),
520
tz.getDstOffsetIndex(save));
521
}
522
}
523
524
currentSave = rrec.getSave();
525
if (fromTime < transition) {
526
tz.addTransition(transition,
527
tz.getOffsetIndex(gmtOffset+currentSave),
528
tz.getDstOffsetIndex(currentSave));
529
tz.addUsedRec(rrec);
530
usedZone = true;
531
}
532
}
533
} else {
534
if (year == fromYear) {
535
tz.addTransition(fromTime,
536
tz.getOffsetIndex(gmtOffset+currentSave),
537
tz.getDstOffsetIndex(currentSave));
538
fromTimeUsed = true;
539
}
540
if (year == endYear && !zrec.hasUntil()) {
541
if (tz.getNTransitions() > 0) {
542
// Assume that this Zone stopped DST
543
tz.setDSTType(Timezone.X_DST);
544
long time = Time.getLocalTime(maxYear, Month.JANUARY,
545
1, 0);
546
time -= zrec.getGmtOffset();
547
tz.addTransition(time,
548
tz.getOffsetIndex(gmtOffset),
549
tz.getDstOffsetIndex(0));
550
usedZone = true;
551
} else {
552
tz.setDSTType(Timezone.NO_DST);
553
}
554
}
555
}
556
}
557
}
558
if (usedZone) {
559
tz.addUsedRec(zrec);
560
}
561
if (zrec.hasUntil() && zrec.getUntilTime(currentSave) > fromTime) {
562
fromTime = zrec.getUntilTime(currentSave);
563
fromYear = zrec.getUntilYear();
564
year = zrec.getUntilYear();
565
}
566
prevzrec = zrec;
567
}
568
569
if (tz.getDSTType() == Timezone.UNDEF_DST) {
570
tz.setDSTType(Timezone.DST);
571
}
572
tz.optimize();
573
tz.checksum();
574
return tz;
575
}
576
577
private static void panic(String msg) {
578
Main.panic(msg);
579
}
580
}
581
582