mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Stdlib: save tzdb as set of rules instead of set of transitions
Generate transitions at run time
This commit is contained in:
parent
71f87d79a5
commit
3cfe4644cd
|
@ -193,9 +193,10 @@ public class DateTimeZoneBuilder {
|
|||
int saveMillis = 0;
|
||||
|
||||
int ruleSetCount = iRuleSets.size();
|
||||
GregorianCalendar calendar = new GregorianCalendar(getGMT());
|
||||
for (int i = 0; i < ruleSetCount; i++) {
|
||||
RuleSet rs = iRuleSets.get(i);
|
||||
Transition next = rs.firstTransition(millis);
|
||||
Transition next = rs.firstTransition(millis, calendar);
|
||||
if (next == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -206,7 +207,7 @@ public class DateTimeZoneBuilder {
|
|||
// Copy it since we're going to destroy it.
|
||||
rs = new RuleSet(rs);
|
||||
|
||||
while ((next = rs.nextTransition(millis, saveMillis)) != null) {
|
||||
while ((next = rs.nextTransition(millis, saveMillis, calendar)) != null) {
|
||||
if (addTransition(transitions, next)) {
|
||||
if (tailZone != null) {
|
||||
// Got the extra transition before DSTZone.
|
||||
|
@ -305,20 +306,52 @@ public class DateTimeZoneBuilder {
|
|||
}
|
||||
|
||||
public void write(StringBuilder sb) {
|
||||
sb.append(iMode);
|
||||
int flags = 0;
|
||||
if (iAdvance) {
|
||||
flags |= 1;
|
||||
}
|
||||
if (iDayOfWeek != 0) {
|
||||
flags |= 2;
|
||||
}
|
||||
switch (iMode) {
|
||||
case 'w':
|
||||
flags |= 4;
|
||||
break;
|
||||
case 's':
|
||||
flags |= 8;
|
||||
break;
|
||||
}
|
||||
Base46.encodeUnsigned(sb, flags);
|
||||
Base46.encodeUnsigned(sb, iMonthOfYear);
|
||||
Base46.encodeUnsigned(sb, iDayOfMonth);
|
||||
if (iDayOfWeek != 0) {
|
||||
Base46.encode(sb, iDayOfWeek);
|
||||
sb.append(iAdvance ? 'y' : 'n');
|
||||
}
|
||||
StorableDateTimeZone.writeUnsignedTime(sb, iMillisOfDay);
|
||||
}
|
||||
|
||||
public static OfYear read(CharFlow flow) {
|
||||
char mode = flow.characters[flow.pointer++];
|
||||
int flags = Base46.decodeUnsigned(flow);
|
||||
boolean advance = (flags & 1) != 0;
|
||||
boolean hasDayOfWeek = (flags & 2) != 0;
|
||||
|
||||
int modeBits = (flags >>> 2) & 3;
|
||||
char mode;
|
||||
switch (modeBits) {
|
||||
case 1:
|
||||
mode = 'w';
|
||||
break;
|
||||
case 2:
|
||||
mode = 's';
|
||||
break;
|
||||
default:
|
||||
mode = 'u';
|
||||
break;
|
||||
}
|
||||
|
||||
int monthOfYear = Base46.decodeUnsigned(flow);
|
||||
int dayOfMonth = Base46.decodeUnsigned(flow);
|
||||
int dayOfWeek = Base46.decode(flow);
|
||||
boolean advance = flow.characters[flow.pointer++] == 'y';
|
||||
int dayOfWeek = hasDayOfWeek ? Base46.decode(flow) : 0;
|
||||
int millisOfDay = (int) StorableDateTimeZone.readUnsignedTime(flow);
|
||||
return new OfYear(mode, monthOfYear, dayOfMonth, dayOfWeek, advance, millisOfDay);
|
||||
}
|
||||
|
@ -358,7 +391,7 @@ public class DateTimeZoneBuilder {
|
|||
/**
|
||||
* @param standardOffset standard offset just before next recurrence
|
||||
*/
|
||||
public long next(long instant, int standardOffset, int saveMillis) {
|
||||
public long next(long instant, int standardOffset, int saveMillis, GregorianCalendar calendar) {
|
||||
int offset;
|
||||
if (iMode == 'w') {
|
||||
offset = standardOffset + saveMillis;
|
||||
|
@ -371,7 +404,6 @@ public class DateTimeZoneBuilder {
|
|||
// Convert from UTC to local time.
|
||||
instant += offset;
|
||||
|
||||
GregorianCalendar calendar = new GregorianCalendar(getGMT());
|
||||
calendar.setTimeInMillis(instant);
|
||||
calendar.set(Calendar.MONTH, iMonthOfYear - 1);
|
||||
calendar.set(Calendar.DATE, 1);
|
||||
|
@ -505,7 +537,7 @@ public class DateTimeZoneBuilder {
|
|||
*/
|
||||
static final class Recurrence {
|
||||
final OfYear iOfYear;
|
||||
final int iSaveMillis;
|
||||
int iSaveMillis;
|
||||
|
||||
Recurrence(OfYear ofYear, int saveMillis) {
|
||||
iOfYear = ofYear;
|
||||
|
@ -519,8 +551,8 @@ public class DateTimeZoneBuilder {
|
|||
/**
|
||||
* @param standardOffset standard offset just before next recurrence
|
||||
*/
|
||||
public long next(long instant, int standardOffset, int saveMillis) {
|
||||
return iOfYear.next(instant, standardOffset, saveMillis);
|
||||
public long next(long instant, int standardOffset, int saveMillis, GregorianCalendar calendar) {
|
||||
return iOfYear.next(instant, standardOffset, saveMillis, calendar);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -578,8 +610,7 @@ public class DateTimeZoneBuilder {
|
|||
return iRecurrence.getSaveMillis();
|
||||
}
|
||||
|
||||
public long next(final long instant, int standardOffset, int saveMillis) {
|
||||
Calendar calendar = Calendar.getInstance(getGMT());
|
||||
public long next(final long instant, int standardOffset, int saveMillis, GregorianCalendar calendar) {
|
||||
final int wallOffset = standardOffset + saveMillis;
|
||||
long testInstant = instant;
|
||||
|
||||
|
@ -591,6 +622,10 @@ public class DateTimeZoneBuilder {
|
|||
year = calendar.get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
if (year > iToYear) {
|
||||
return instant;
|
||||
}
|
||||
|
||||
if (year < iFromYear) {
|
||||
calendar.setTimeInMillis(0);
|
||||
calendar.set(Calendar.YEAR, iFromYear);
|
||||
|
@ -601,7 +636,7 @@ public class DateTimeZoneBuilder {
|
|||
testInstant -= 1;
|
||||
}
|
||||
|
||||
long next = iRecurrence.next(testInstant, standardOffset, saveMillis);
|
||||
long next = iRecurrence.next(testInstant, standardOffset, saveMillis, calendar);
|
||||
|
||||
if (next > instant) {
|
||||
calendar.setTimeInMillis(next + wallOffset);
|
||||
|
@ -662,7 +697,8 @@ public class DateTimeZoneBuilder {
|
|||
if (other == null) {
|
||||
return true;
|
||||
}
|
||||
return iMillis > other.iMillis && iWallOffset != other.iWallOffset;
|
||||
return iMillis > other.iMillis
|
||||
&& (iWallOffset != other.iWallOffset || iStandardOffset != other.iStandardOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -737,7 +773,7 @@ public class DateTimeZoneBuilder {
|
|||
*
|
||||
* @param firstMillis millis of first transition
|
||||
*/
|
||||
public Transition firstTransition(final long firstMillis) {
|
||||
public Transition firstTransition(final long firstMillis, GregorianCalendar calendar) {
|
||||
if (iInitialNameKey != null) {
|
||||
// Initial zone info explicitly set, so don't search the rules.
|
||||
return new Transition(firstMillis, iStandardOffset + iInitialSaveMillis, iStandardOffset);
|
||||
|
@ -755,7 +791,7 @@ public class DateTimeZoneBuilder {
|
|||
Transition first = null;
|
||||
|
||||
Transition next;
|
||||
while ((next = nextTransition(millis, saveMillis)) != null) {
|
||||
while ((next = nextTransition(millis, saveMillis, calendar)) != null) {
|
||||
millis = next.getMillis();
|
||||
|
||||
if (millis == firstMillis) {
|
||||
|
@ -768,7 +804,7 @@ public class DateTimeZoneBuilder {
|
|||
// Find first rule without savings. This way a more
|
||||
// accurate nameKey is found even though no rule
|
||||
// extends to the RuleSet's lower limit.
|
||||
for (Rule rule : copy) {
|
||||
for (Rule rule : iRules) {
|
||||
if (rule.getSaveMillis() == 0) {
|
||||
first = new Transition(firstMillis, rule, iStandardOffset);
|
||||
break;
|
||||
|
@ -806,15 +842,20 @@ public class DateTimeZoneBuilder {
|
|||
*
|
||||
* @param saveMillis savings before next transition
|
||||
*/
|
||||
public Transition nextTransition(final long instant, final int saveMillis) {
|
||||
public Transition nextTransition(long instant, int saveMillis, GregorianCalendar calendar) {
|
||||
// Find next matching rule.
|
||||
Rule nextRule = null;
|
||||
long nextMillis = Long.MAX_VALUE;
|
||||
int nextYear = Integer.MAX_VALUE;
|
||||
|
||||
Iterator<Rule> it = iRules.iterator();
|
||||
while (it.hasNext()) {
|
||||
Rule rule = it.next();
|
||||
long next = rule.next(instant, iStandardOffset, saveMillis);
|
||||
if (rule.iFromYear > nextYear) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long next = rule.next(instant, iStandardOffset, saveMillis, calendar);
|
||||
if (next <= instant) {
|
||||
it.remove();
|
||||
continue;
|
||||
|
@ -825,6 +866,7 @@ public class DateTimeZoneBuilder {
|
|||
// Found a better match.
|
||||
nextRule = rule;
|
||||
nextMillis = next;
|
||||
nextYear = calendar.get(Calendar.YEAR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -833,16 +875,14 @@ public class DateTimeZoneBuilder {
|
|||
}
|
||||
|
||||
// Stop precalculating if year reaches some arbitrary limit.
|
||||
Calendar c = Calendar.getInstance(getGMT());
|
||||
c.setTimeInMillis(nextMillis);
|
||||
if (c.get(Calendar.YEAR) >= YEAR_LIMIT) {
|
||||
calendar.setTimeInMillis(nextMillis);
|
||||
if (calendar.get(Calendar.YEAR) >= YEAR_LIMIT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if upper limit reached or passed.
|
||||
if (iUpperYear < Integer.MAX_VALUE) {
|
||||
long upperMillis =
|
||||
iUpperOfYear.setInstant(iUpperYear, iStandardOffset, saveMillis);
|
||||
long upperMillis = iUpperOfYear.setInstant(iUpperYear, iStandardOffset, saveMillis);
|
||||
if (nextMillis >= upperMillis) {
|
||||
// At or after upper limit.
|
||||
return null;
|
||||
|
@ -890,6 +930,7 @@ public class DateTimeZoneBuilder {
|
|||
final int iStandardOffset;
|
||||
final Recurrence iStartRecurrence;
|
||||
final Recurrence iEndRecurrence;
|
||||
final GregorianCalendar calendar = new GregorianCalendar(getGMT());
|
||||
|
||||
DSTZone(String id, int standardOffset, Recurrence startRecurrence, Recurrence endRecurrence) {
|
||||
super(id);
|
||||
|
@ -923,7 +964,7 @@ public class DateTimeZoneBuilder {
|
|||
long end;
|
||||
|
||||
try {
|
||||
start = startRecurrence.next(instant, standardOffset, endRecurrence.getSaveMillis());
|
||||
start = startRecurrence.next(instant, standardOffset, endRecurrence.getSaveMillis(), calendar);
|
||||
if (instant > 0 && start < 0) {
|
||||
// Overflowed.
|
||||
start = instant;
|
||||
|
@ -934,7 +975,7 @@ public class DateTimeZoneBuilder {
|
|||
}
|
||||
|
||||
try {
|
||||
end = endRecurrence.next(instant, standardOffset, startRecurrence.getSaveMillis());
|
||||
end = endRecurrence.next(instant, standardOffset, startRecurrence.getSaveMillis(), calendar);
|
||||
if (instant > 0 && end < 0) {
|
||||
// Overflowed.
|
||||
end = instant;
|
||||
|
@ -994,14 +1035,14 @@ public class DateTimeZoneBuilder {
|
|||
long end;
|
||||
|
||||
try {
|
||||
start = startRecurrence.next(instant, standardOffset, endRecurrence.getSaveMillis());
|
||||
start = startRecurrence.next(instant, standardOffset, endRecurrence.getSaveMillis(), calendar);
|
||||
} catch (IllegalArgumentException | ArithmeticException e) {
|
||||
// Overflowed.
|
||||
start = instant;
|
||||
}
|
||||
|
||||
try {
|
||||
end = endRecurrence.next(instant, standardOffset, startRecurrence.getSaveMillis());
|
||||
end = endRecurrence.next(instant, standardOffset, startRecurrence.getSaveMillis(), calendar);
|
||||
} catch (IllegalArgumentException | ArithmeticException e) {
|
||||
// Overflowed.
|
||||
end = instant;
|
||||
|
@ -1092,18 +1133,39 @@ public class DateTimeZoneBuilder {
|
|||
++start;
|
||||
}
|
||||
|
||||
if (start > 1) {
|
||||
--start;
|
||||
iTransitions[start] = iTransitions[0];
|
||||
iWallOffsets[start] = iWallOffsets[0];
|
||||
iStandardOffsets[start] = iStandardOffsets[0];
|
||||
}
|
||||
|
||||
Base46.encodeUnsigned(sb, PRECALCULATED);
|
||||
Base46.encodeUnsigned(sb, iTransitions.length - start);
|
||||
|
||||
int lengthEncoded = (iTransitions.length - start) << 1;
|
||||
if (iTransitions[start] == Long.MIN_VALUE) {
|
||||
lengthEncoded |= 1;
|
||||
}
|
||||
Base46.encodeUnsigned(sb, lengthEncoded);
|
||||
|
||||
long[] transitions = iTransitions.clone();
|
||||
for (int i = 0; i < transitions.length; ++i) {
|
||||
transitions[i] = (transitions[i] / 60_000) * 60_000;
|
||||
}
|
||||
|
||||
if (iTransitions[start] == Long.MIN_VALUE) {
|
||||
if (start + 1 < transitions.length) {
|
||||
writeTime(sb, transitions[start + 1]);
|
||||
for (int i = start + 2; i < transitions.length; ++i) {
|
||||
writeTime(sb, transitions[i] - transitions[i - 1] - (365 * 3600 * 1000 / 2));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeTime(sb, transitions[start]);
|
||||
for (int i = start + 1; i < transitions.length; ++i) {
|
||||
writeTime(sb, transitions[i] - transitions[i - 1] - (365 * 3600 * 1000 / 2));
|
||||
}
|
||||
}
|
||||
|
||||
writeTimeArray(sb, Arrays.copyOfRange(iWallOffsets, start, transitions.length));
|
||||
writeTimeArray(sb, Arrays.copyOfRange(iStandardOffsets, start, transitions.length));
|
||||
|
@ -1118,14 +1180,26 @@ public class DateTimeZoneBuilder {
|
|||
|
||||
public static StorableDateTimeZone readZone(String id, CharFlow flow) {
|
||||
int length = Base46.decodeUnsigned(flow);
|
||||
boolean firstLongIsMin = (length & 1) != 0;
|
||||
length >>>= 1;
|
||||
long[] transitions = new long[length];
|
||||
int[] wallOffsets = new int[length];
|
||||
int[] standardOffsets = new int[length];
|
||||
|
||||
if (firstLongIsMin) {
|
||||
transitions[0] = Long.MIN_VALUE;
|
||||
if (transitions.length > 1) {
|
||||
transitions[1] = readTime(flow);
|
||||
for (int i = 2; i < length; ++i) {
|
||||
transitions[i] = transitions[i - 1] + readTime(flow) + 365 * 3600 * 1000 / 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
transitions[0] = readTime(flow);
|
||||
for (int i = 1; i < length; ++i) {
|
||||
transitions[i] = transitions[i - 1] + readTime(flow) + 365 * 3600 * 1000 / 2;
|
||||
}
|
||||
}
|
||||
|
||||
readTimeArray(flow, wallOffsets);
|
||||
readTimeArray(flow, standardOffsets);
|
||||
|
@ -1277,4 +1351,175 @@ public class DateTimeZoneBuilder {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static final class RuleBasedZone extends StorableDateTimeZone {
|
||||
private DateTimeZoneBuilder builder;
|
||||
private DateTimeZone zone;
|
||||
|
||||
RuleBasedZone(String id, DateTimeZoneBuilder builder) {
|
||||
super(id);
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
private void initZone() {
|
||||
if (zone == null) {
|
||||
zone = builder.toDateTimeZone(getID(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset(long instant) {
|
||||
initZone();
|
||||
return zone.getOffset(instant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStandardOffset(long instant) {
|
||||
initZone();
|
||||
return zone.getStandardOffset(instant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFixed() {
|
||||
initZone();
|
||||
return zone.isFixed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextTransition(long instant) {
|
||||
initZone();
|
||||
return zone.nextTransition(instant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long previousTransition(long instant) {
|
||||
initZone();
|
||||
return zone.previousTransition(instant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(StringBuilder sb) {
|
||||
Base46.encodeUnsigned(sb, RULE_BASED);
|
||||
Base46.encodeUnsigned(sb, builder.iRuleSets.size());
|
||||
int currentYear = Integer.MIN_VALUE;
|
||||
int fromYear = currentYear;
|
||||
for (RuleSet rs : builder.iRuleSets) {
|
||||
writeTime(sb, rs.iInitialSaveMillis);
|
||||
writeTime(sb, rs.iStandardOffset);
|
||||
List<Rule> rules = filterRules(fromYear, rs.iUpperYear, rs.iRules);
|
||||
Base46.encodeUnsigned(sb, (rules.size() << 1) | (rs.iInitialNameKey != null ? 1 : 0));
|
||||
for (Rule rule : rules) {
|
||||
if (currentYear == Integer.MIN_VALUE) {
|
||||
Base46.encode(sb, rule.getFromYear());
|
||||
} else {
|
||||
Base46.encode(sb, rule.getFromYear() - currentYear);
|
||||
}
|
||||
currentYear = rule.getFromYear();
|
||||
if (rule.getToYear() != Integer.MAX_VALUE) {
|
||||
int yearDelta = rule.getToYear() - currentYear;
|
||||
if (yearDelta < 0) {
|
||||
yearDelta = (-yearDelta - 1) << 1 | 1;
|
||||
} else {
|
||||
yearDelta = yearDelta << 1;
|
||||
}
|
||||
Base46.encodeUnsigned(sb, yearDelta + 1);
|
||||
currentYear = rule.getToYear();
|
||||
} else {
|
||||
Base46.encodeUnsigned(sb, 0);
|
||||
}
|
||||
rule.iRecurrence.write(sb);
|
||||
}
|
||||
if (rs.iUpperYear == Integer.MAX_VALUE) {
|
||||
Base46.encodeUnsigned(sb, 0);
|
||||
} else {
|
||||
int encodedYear;
|
||||
if (currentYear == Integer.MIN_VALUE) {
|
||||
encodedYear = rs.iUpperYear;
|
||||
} else {
|
||||
encodedYear = rs.iUpperYear - currentYear;
|
||||
}
|
||||
encodedYear = encodedYear < 0 ? ((-encodedYear - 1) << 1) | 1 : encodedYear << 1;
|
||||
Base46.encodeUnsigned(sb, encodedYear + 1);
|
||||
rs.iUpperOfYear.write(sb);
|
||||
currentYear = rs.iUpperYear;
|
||||
}
|
||||
fromYear = rs.iUpperYear;
|
||||
}
|
||||
}
|
||||
|
||||
public static StorableDateTimeZone readZone(String id, CharFlow flow) {
|
||||
DateTimeZoneBuilder builder = new DateTimeZoneBuilder();
|
||||
int ruleSetCount = Base46.decodeUnsigned(flow);
|
||||
int currentYear = Integer.MIN_VALUE;
|
||||
for (int i = 0; i < ruleSetCount; ++i) {
|
||||
RuleSet rs = new RuleSet();
|
||||
rs.iInitialSaveMillis = (int) readTime(flow);
|
||||
rs.iStandardOffset = (int) readTime(flow);
|
||||
int ruleCount = Base46.decodeUnsigned(flow);
|
||||
if ((ruleCount & 1) != 0) {
|
||||
rs.iInitialNameKey = "*";
|
||||
}
|
||||
ruleCount >>>= 1;
|
||||
for (int j = 0; j < ruleCount; ++j) {
|
||||
int fromYear = Base46.decode(flow);
|
||||
if (currentYear != Integer.MIN_VALUE) {
|
||||
fromYear += currentYear;
|
||||
}
|
||||
currentYear = fromYear;
|
||||
int toYear = Base46.decodeUnsigned(flow);
|
||||
if (toYear == 0) {
|
||||
toYear = Integer.MAX_VALUE;
|
||||
} else {
|
||||
toYear--;
|
||||
toYear = (toYear & 1) == 0 ? toYear >>> 1 : -(toYear >>> 1) - 1;
|
||||
if (currentYear != Integer.MIN_VALUE) {
|
||||
toYear += currentYear;
|
||||
}
|
||||
currentYear = toYear;
|
||||
}
|
||||
Recurrence recurrence = Recurrence.read(flow);
|
||||
rs.iRules.add(new Rule(recurrence, fromYear, toYear));
|
||||
}
|
||||
int year = Base46.decodeUnsigned(flow);
|
||||
if (year == 0) {
|
||||
rs.iUpperYear = Integer.MAX_VALUE;
|
||||
} else {
|
||||
year--;
|
||||
if ((year & 1) == 0) {
|
||||
year >>>= 1;
|
||||
} else {
|
||||
year = -(year >>> 1) - 1;
|
||||
}
|
||||
if (currentYear != Integer.MIN_VALUE) {
|
||||
year += currentYear;
|
||||
}
|
||||
rs.iUpperYear = year;
|
||||
rs.iUpperOfYear = OfYear.read(flow);
|
||||
currentYear = year;
|
||||
}
|
||||
builder.iRuleSets.add(rs);
|
||||
}
|
||||
|
||||
return new RuleBasedZone(id, builder);
|
||||
}
|
||||
|
||||
private List<Rule> filterRules(int fromYear, int toYear, List<Rule> rules) {
|
||||
List<Rule> filtered = new ArrayList<>();
|
||||
if (fromYear != Integer.MIN_VALUE) {
|
||||
int bestYear = Integer.MIN_VALUE;
|
||||
for (Rule rule : rules) {
|
||||
if (rule.getToYear() < fromYear && rule.getToYear() > bestYear) {
|
||||
bestYear = rule.getToYear();
|
||||
}
|
||||
}
|
||||
fromYear = bestYear;
|
||||
}
|
||||
for (Rule rule : rules) {
|
||||
if (rule.getToYear() >= fromYear && rule.getFromYear() <= toYear) {
|
||||
filtered.add(rule);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,14 @@ import org.teavm.classlib.impl.Base46;
|
|||
import org.teavm.classlib.impl.CharFlow;
|
||||
import org.teavm.classlib.impl.tz.DateTimeZoneBuilder.DSTZone;
|
||||
import org.teavm.classlib.impl.tz.DateTimeZoneBuilder.PrecalculatedZone;
|
||||
import org.teavm.classlib.impl.tz.DateTimeZoneBuilder.RuleBasedZone;
|
||||
|
||||
public abstract class StorableDateTimeZone extends DateTimeZone {
|
||||
public static final int PRECALCULATED = 0;
|
||||
public static final int FIXED = 1;
|
||||
public static final int DST = 3;
|
||||
public static final int ALIAS = 4;
|
||||
public static final int RULE_BASED = 5;
|
||||
|
||||
public StorableDateTimeZone(String id) {
|
||||
super(id);
|
||||
|
@ -34,9 +36,9 @@ public abstract class StorableDateTimeZone extends DateTimeZone {
|
|||
|
||||
public static void writeTime(StringBuilder sb, long time) {
|
||||
if (time % 1800_000 == 0) {
|
||||
Base46.encode(sb, (int) ((time / 1800_000) << 1));
|
||||
Base46.encode(sb, (time / 1800_000) << 1);
|
||||
} else {
|
||||
Base46.encode(sb, (int) (((time / 60_000) << 1) | 1));
|
||||
Base46.encode(sb, (time << 1) | 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +47,7 @@ public abstract class StorableDateTimeZone extends DateTimeZone {
|
|||
if ((value & 1) == 0) {
|
||||
return (value >> 1) * 1800_000;
|
||||
} else {
|
||||
return (value >> 1) * 60_000;
|
||||
return value >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +55,7 @@ public abstract class StorableDateTimeZone extends DateTimeZone {
|
|||
if (time % 1800_000 == 0) {
|
||||
Base46.encodeUnsigned(sb, (int) ((time / 1800_000) << 1));
|
||||
} else {
|
||||
Base46.encodeUnsigned(sb, (int) (((time / 60_000) << 1) | 1));
|
||||
Base46.encodeUnsigned(sb, (int) ((time << 1) | 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +64,7 @@ public abstract class StorableDateTimeZone extends DateTimeZone {
|
|||
if ((value & 1) == 0) {
|
||||
return (value >>> 1) * 1800_000;
|
||||
} else {
|
||||
return (value >>> 1) * 60_000;
|
||||
return value >>> 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +126,8 @@ public abstract class StorableDateTimeZone extends DateTimeZone {
|
|||
return DSTZone.readZone(id, flow);
|
||||
case FIXED:
|
||||
return FixedDateTimeZone.readZone(id, flow);
|
||||
case RULE_BASED:
|
||||
return RuleBasedZone.readZone(id, flow);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown zone type: " + type);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ public class TimeZoneCache {
|
|||
String data = aliasLine.substring(index + 1);
|
||||
CharFlow flow = new CharFlow(data.toCharArray());
|
||||
Base46.decode(flow);
|
||||
result.put(id, result.get(data.substring(flow.pointer)));
|
||||
result.put(id, new AliasDateTimeZone(id, result.get(data.substring(flow.pointer))));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@ public class ZoneInfoCompiler {
|
|||
long end = ISOChronology.getInstanceUTC().year().set(0, 2050);
|
||||
|
||||
int offset = tz.getOffset(millis);
|
||||
int stdOffset = tz.getStandardOffset(millis);
|
||||
|
||||
List<Long> transitions = new ArrayList<>();
|
||||
|
||||
|
@ -140,16 +141,18 @@ public class ZoneInfoCompiler {
|
|||
millis = next;
|
||||
|
||||
int nextOffset = tz.getOffset(millis);
|
||||
int nextStdOffset = tz.getStandardOffset(millis);
|
||||
|
||||
if (offset == nextOffset) {
|
||||
if (offset == nextOffset && stdOffset == nextStdOffset) {
|
||||
System.out.println("*d* Error in " + tz.getID() + " "
|
||||
+ new DateTime(millis, ISOChronology.getInstanceUTC()));
|
||||
return false;
|
||||
}
|
||||
|
||||
transitions.add(Long.valueOf(millis));
|
||||
transitions.add(millis);
|
||||
|
||||
offset = nextOffset;
|
||||
stdOffset = nextStdOffset;
|
||||
}
|
||||
|
||||
// Now verify that reverse transitions match up.
|
||||
|
@ -165,7 +168,7 @@ public class ZoneInfoCompiler {
|
|||
|
||||
millis = prev;
|
||||
|
||||
long trans = transitions.get(i).longValue();
|
||||
long trans = transitions.get(i);
|
||||
|
||||
if (trans - 1 != millis) {
|
||||
System.out.println("*r* Error in " + tz.getID() + " "
|
||||
|
@ -203,11 +206,10 @@ public class ZoneInfoCompiler {
|
|||
Map<String, Zone> sourceMap = new TreeMap<>();
|
||||
|
||||
// write out the standard entries
|
||||
for (int i = 0; i < iZones.size(); i++) {
|
||||
Zone zone = iZones.get(i);
|
||||
for (Zone zone : iZones) {
|
||||
DateTimeZoneBuilder builder = new DateTimeZoneBuilder();
|
||||
zone.addToBuilder(builder, iRuleSets);
|
||||
StorableDateTimeZone tz = builder.toDateTimeZone(zone.iName, true);
|
||||
StorableDateTimeZone tz = new DateTimeZoneBuilder.RuleBasedZone(zone.iName, builder);
|
||||
if (test(tz.getID(), tz)) {
|
||||
map.put(tz.getID(), tz);
|
||||
sourceMap.put(tz.getID(), zone);
|
||||
|
@ -225,7 +227,7 @@ public class ZoneInfoCompiler {
|
|||
} else {
|
||||
DateTimeZoneBuilder builder = new DateTimeZoneBuilder();
|
||||
sourceZone.addToBuilder(builder, iRuleSets);
|
||||
StorableDateTimeZone revived = builder.toDateTimeZone(alias, true);
|
||||
StorableDateTimeZone revived = new DateTimeZoneBuilder.RuleBasedZone(alias, builder);
|
||||
if (test(revived.getID(), revived)) {
|
||||
map.put(revived.getID(), revived);
|
||||
}
|
||||
|
@ -604,7 +606,7 @@ public class ZoneInfoCompiler {
|
|||
return str;
|
||||
}
|
||||
|
||||
return str + "...\n" + iNext.toString();
|
||||
return str + "...\n" + iNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user