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