use of android.icu.util.BasicTimeZone in project j2objc by google.
the class TimeZoneOffsetLocalTest method TestGetOffsetAroundTransition.
/*
* Testing getOffset APIs around rule transition by local standard/wall time.
*/
@Test
public void TestGetOffsetAroundTransition() {
final int HOUR = 60 * 60 * 1000;
final int MINUTE = 60 * 1000;
int[][] DATES = { { 2006, Calendar.APRIL, 2, 1, 30, 1 * HOUR + 30 * MINUTE }, { 2006, Calendar.APRIL, 2, 2, 00, 2 * HOUR }, { 2006, Calendar.APRIL, 2, 2, 30, 2 * HOUR + 30 * MINUTE }, { 2006, Calendar.APRIL, 2, 3, 00, 3 * HOUR }, { 2006, Calendar.APRIL, 2, 3, 30, 3 * HOUR + 30 * MINUTE }, { 2006, Calendar.OCTOBER, 29, 0, 30, 0 * HOUR + 30 * MINUTE }, { 2006, Calendar.OCTOBER, 29, 1, 00, 1 * HOUR }, { 2006, Calendar.OCTOBER, 29, 1, 30, 1 * HOUR + 30 * MINUTE }, { 2006, Calendar.OCTOBER, 29, 2, 00, 2 * HOUR }, { 2006, Calendar.OCTOBER, 29, 2, 30, 2 * HOUR + 30 * MINUTE } };
// Expected offsets by getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds)
int[] OFFSETS1 = { // April 2, 2006
-8 * HOUR, -7 * HOUR, -7 * HOUR, -7 * HOUR, -7 * HOUR, // October 29, 2006
-7 * HOUR, -8 * HOUR, -8 * HOUR, -8 * HOUR, -8 * HOUR };
// Expected offsets by getOffset(long time, boolean local, int[] offsets) with local = true
// or getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
// with nonExistingTimeOpt = LOCAL_STD/duplicatedTimeOpt = LOCAL_STD
int[][] OFFSETS2 = { // April 2, 2006
{ -8 * HOUR, 0 }, { -8 * HOUR, 0 }, { -8 * HOUR, 0 }, { -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 1 * HOUR }, // Oct 29, 2006
{ -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 0 }, { -8 * HOUR, 0 }, { -8 * HOUR, 0 }, { -8 * HOUR, 0 } };
// Expected offsets by getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
// with nonExistingTimeOpt = LOCAL_DST/duplicatedTimeOpt = LOCAL_DST
int[][] OFFSETS3 = { // April 2, 2006
{ -8 * HOUR, 0 }, { -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 1 * HOUR }, // October 29, 2006
{ -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 1 * HOUR }, { -8 * HOUR, 0 }, { -8 * HOUR, 0 } };
int[] offsets = new int[2];
TimeZone utc = TimeZone.getTimeZone("UTC");
Calendar cal = Calendar.getInstance(utc);
cal.clear();
// Set up TimeZone objects - OlsonTimeZone, SimpleTimeZone and RuleBasedTimeZone
BasicTimeZone[] TESTZONES = new BasicTimeZone[3];
TESTZONES[0] = (BasicTimeZone) TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_ICU);
TESTZONES[1] = new SimpleTimeZone(-8 * HOUR, "Simple Pacific Time", Calendar.APRIL, 1, Calendar.SUNDAY, 2 * HOUR, Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * HOUR);
InitialTimeZoneRule ir = new InitialTimeZoneRule(// Initial time Name
"Pacific Standard Time", // Raw offset
-8 * HOUR, // DST saving amount
0 * HOUR);
RuleBasedTimeZone rbPT = new RuleBasedTimeZone("Rule based Pacific Time", ir);
DateTimeRule dtr;
AnnualTimeZoneRule atzr;
final int STARTYEAR = 2000;
dtr = new DateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * HOUR, // 1st Sunday in April, at 2AM wall time
DateTimeRule.WALL_TIME);
atzr = new AnnualTimeZoneRule("Pacific Daylight Time", -8 * HOUR, /* rawOffset */
1 * HOUR, /* dstSavings */
dtr, STARTYEAR, AnnualTimeZoneRule.MAX_YEAR);
rbPT.addTransitionRule(atzr);
dtr = new DateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * HOUR, // last Sunday in October, at 2AM wall time
DateTimeRule.WALL_TIME);
atzr = new AnnualTimeZoneRule("Pacific Standard Time", -8 * HOUR, /* rawOffset */
0, /* dstSavings */
dtr, STARTYEAR, AnnualTimeZoneRule.MAX_YEAR);
rbPT.addTransitionRule(atzr);
TESTZONES[2] = rbPT;
// Calculate millis
long[] MILLIS = new long[DATES.length];
for (int i = 0; i < DATES.length; i++) {
cal.clear();
cal.set(DATES[i][0], DATES[i][1], DATES[i][2], DATES[i][3], DATES[i][4]);
MILLIS[i] = cal.getTimeInMillis();
}
DateFormat df = DateFormat.getInstance();
df.setTimeZone(utc);
// Test getOffset(int era, int year, int month, int day, int dayOfWeek, int millis)
for (int i = 0; i < TESTZONES.length; i++) {
for (int d = 0; d < DATES.length; d++) {
int offset = TESTZONES[i].getOffset(GregorianCalendar.AD, DATES[d][0], DATES[d][1], DATES[d][2], Calendar.SUNDAY, DATES[d][5]);
if (offset != OFFSETS1[d]) {
errln("Bad offset returned by " + TESTZONES[i].getID() + " at " + df.format(new Date(MILLIS[d])) + "(standard) - Got: " + offset + " Expected: " + OFFSETS1[d]);
}
}
}
// Test getOffset(long time, boolean local, int[] offsets) with local=true
for (int i = 0; i < TESTZONES.length; i++) {
for (int m = 0; m < MILLIS.length; m++) {
TESTZONES[i].getOffset(MILLIS[m], true, offsets);
if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
errln("Bad offset returned by " + TESTZONES[i].getID() + " at " + df.format(new Date(MILLIS[m])) + "(wall) - Got: " + offsets[0] + "/" + offsets[1] + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
}
}
}
// with nonExistingTimeOpt = LOCAL_STD/duplicatedTimeOpt = LOCAL_STD
for (int i = 0; i < TESTZONES.length; i++) {
for (int m = 0; m < MILLIS.length; m++) {
TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_STD, BasicTimeZone.LOCAL_STD, offsets);
if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
errln("Bad offset returned by " + TESTZONES[i].getID() + " at " + df.format(new Date(MILLIS[m])) + "(wall/STD/STD) - Got: " + offsets[0] + "/" + offsets[1] + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
}
}
}
// with nonExistingTimeOpt = LOCAL_DST/duplicatedTimeOpt = LOCAL_DST
for (int i = 0; i < TESTZONES.length; i++) {
for (int m = 0; m < MILLIS.length; m++) {
TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_DST, BasicTimeZone.LOCAL_DST, offsets);
if (offsets[0] != OFFSETS3[m][0] || offsets[1] != OFFSETS3[m][1]) {
errln("Bad offset returned by " + TESTZONES[i].getID() + " at " + df.format(new Date(MILLIS[m])) + "(wall/DST/DST) - Got: " + offsets[0] + "/" + offsets[1] + " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]);
}
}
}
// with nonExistingTimeOpt = LOCAL_FORMER/duplicatedTimeOpt = LOCAL_LATTER
for (int i = 0; i < TESTZONES.length; i++) {
for (int m = 0; m < MILLIS.length; m++) {
TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_FORMER, BasicTimeZone.LOCAL_LATTER, offsets);
if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
errln("Bad offset returned by " + TESTZONES[i].getID() + " at " + df.format(new Date(MILLIS[m])) + "(wall/FORMER/LATTER) - Got: " + offsets[0] + "/" + offsets[1] + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
}
}
}
// with nonExistingTimeOpt = LOCAL_LATTER/duplicatedTimeOpt = LOCAL_FORMER
for (int i = 0; i < TESTZONES.length; i++) {
for (int m = 0; m < MILLIS.length; m++) {
TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_LATTER, BasicTimeZone.LOCAL_FORMER, offsets);
if (offsets[0] != OFFSETS3[m][0] || offsets[1] != OFFSETS3[m][1]) {
errln("Bad offset returned by " + TESTZONES[i].getID() + " at " + df.format(new Date(MILLIS[m])) + "(wall/LATTER/FORMER) - Got: " + offsets[0] + "/" + offsets[1] + " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]);
}
}
}
}
use of android.icu.util.BasicTimeZone in project j2objc by google.
the class TimeZoneRuleTest method TestRBTZTransition.
/*
* Check if an OlsonTimeZone and its equivalent RBTZ have the exact same
* transitions.
*/
@Test
public void TestRBTZTransition() {
int[] STARTYEARS = { 1950, 1975, 2000, 2010 };
String[] zids = getTestZIDs();
for (int i = 0; i < zids.length; i++) {
TimeZone tz = TimeZone.getTimeZone(zids[i], TimeZone.TIMEZONE_ICU);
if (tz == null) {
break;
}
for (int j = 0; j < STARTYEARS.length; j++) {
long startTime = getUTCMillis(STARTYEARS[j], Calendar.JANUARY, 1);
TimeZoneRule[] rules = ((BasicTimeZone) tz).getTimeZoneRules(startTime);
RuleBasedTimeZone rbtz = new RuleBasedTimeZone(tz.getID() + "(RBTZ)", (InitialTimeZoneRule) rules[0]);
for (int k = 1; k < rules.length; k++) {
rbtz.addTransitionRule(rules[k]);
}
// Compare the original OlsonTimeZone with the RBTZ starting the startTime for 20 years
long until = getUTCMillis(STARTYEARS[j] + 20, Calendar.JANUARY, 1);
// Ascending
compareTransitionsAscending(tz, rbtz, startTime, until, false);
// Ascending/inclusive
compareTransitionsAscending(tz, rbtz, startTime + 1, until, true);
// Descending
compareTransitionsDescending(tz, rbtz, startTime, until, false);
// Descending/inclusive
compareTransitionsDescending(tz, rbtz, startTime + 1, until, true);
}
}
}
use of android.icu.util.BasicTimeZone in project j2objc by google.
the class TimeZoneFormatTest method TestTimeRoundTrip.
/*
* Test case of round trip time and text. This test case detects every canonical TimeZone's
* rule transition since 1900 until 2020, then check if time around each transition can
* round trip as expected.
*/
@Test
public void TestTimeRoundTrip() {
boolean TEST_ALL = getBooleanProperty("TimeZoneRoundTripAll", false);
int startYear, endYear;
if (TEST_ALL || TestFmwk.getExhaustiveness() > 5) {
startYear = 1900;
} else {
startYear = 1990;
}
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
endYear = cal.get(Calendar.YEAR) + 3;
cal.set(startYear, Calendar.JANUARY, 1);
final long START_TIME = cal.getTimeInMillis();
cal.set(endYear, Calendar.JANUARY, 1);
final long END_TIME = cal.getTimeInMillis();
// These patterns are ambiguous at DST->STD local time overlap
List<String> AMBIGUOUS_DST_DECESSION = Arrays.asList("v", "vvvv", "V", "VV", "VVV", "VVVV");
// These patterns are ambiguous at STD->STD/DST->DST local time overlap
List<String> AMBIGUOUS_NEGATIVE_SHIFT = Arrays.asList("z", "zzzz", "v", "vvvv", "V", "VV", "VVV", "VVVV");
// These patterns only support integer minutes offset
List<String> MINUTES_OFFSET = Arrays.asList("X", "XX", "XXX", "x", "xx", "xxx");
// Regex pattern used for filtering zone IDs without exemplar location
final Pattern LOC_EXCLUSION_PATTERN = Pattern.compile("Etc/.*|SystemV/.*|.*/Riyadh8[7-9]");
final String BASEPATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS";
ULocale[] LOCALES = null;
// timer for performance analysis
long[] times = new long[PATTERNS.length];
long timer;
if (TEST_ALL) {
// It may take about an hour for testing all locales
LOCALES = ULocale.getAvailableLocales();
} else if (TestFmwk.getExhaustiveness() > 5) {
LOCALES = new ULocale[] { new ULocale("ar_EG"), new ULocale("bg_BG"), new ULocale("ca_ES"), new ULocale("da_DK"), new ULocale("de"), new ULocale("de_DE"), new ULocale("el_GR"), new ULocale("en"), new ULocale("en_AU"), new ULocale("en_CA"), new ULocale("en_US"), new ULocale("es"), new ULocale("es_ES"), new ULocale("es_MX"), new ULocale("fi_FI"), new ULocale("fr"), new ULocale("fr_CA"), new ULocale("fr_FR"), new ULocale("he_IL"), new ULocale("hu_HU"), new ULocale("it"), new ULocale("it_IT"), new ULocale("ja"), new ULocale("ja_JP"), new ULocale("ko"), new ULocale("ko_KR"), new ULocale("nb_NO"), new ULocale("nl_NL"), new ULocale("nn_NO"), new ULocale("pl_PL"), new ULocale("pt"), new ULocale("pt_BR"), new ULocale("pt_PT"), new ULocale("ru_RU"), new ULocale("sv_SE"), new ULocale("th_TH"), new ULocale("tr_TR"), new ULocale("zh"), new ULocale("zh_Hans"), new ULocale("zh_Hans_CN"), new ULocale("zh_Hant"), new ULocale("zh_Hant_HK"), new ULocale("zh_Hant_TW") };
} else {
LOCALES = new ULocale[] { new ULocale("en") };
}
SimpleDateFormat sdfGMT = new SimpleDateFormat(BASEPATTERN);
sdfGMT.setTimeZone(TimeZone.getTimeZone("Etc/GMT"));
long testCounts = 0;
long[] testTimes = new long[4];
boolean[] expectedRoundTrip = new boolean[4];
int testLen = 0;
for (int locidx = 0; locidx < LOCALES.length; locidx++) {
logln("Locale: " + LOCALES[locidx].toString());
for (int patidx = 0; patidx < PATTERNS.length; patidx++) {
logln(" pattern: " + PATTERNS[patidx]);
String pattern = BASEPATTERN + " " + PATTERNS[patidx];
SimpleDateFormat sdf = new SimpleDateFormat(pattern, LOCALES[locidx]);
boolean minutesOffset = MINUTES_OFFSET.contains(PATTERNS[patidx]);
Set<String> ids = null;
if (JDKTZ) {
ids = new TreeSet<String>();
String[] jdkIDs = java.util.TimeZone.getAvailableIDs();
for (String jdkID : jdkIDs) {
if (EXCL_TZ_PATTERN.matcher(jdkID).matches()) {
continue;
}
String tmpID = TimeZone.getCanonicalID(jdkID);
if (tmpID != null) {
ids.add(tmpID);
}
}
} else {
ids = TimeZone.getAvailableIDs(SystemTimeZoneType.CANONICAL, null, null);
}
for (String id : ids) {
if (PATTERNS[patidx].equals("V")) {
// Some zones do not have short ID assigned, such as Asia/Riyadh87.
// The time roundtrip will fail for such zones with pattern "V" (short zone ID).
// This is expected behavior.
String shortZoneID = ZoneMeta.getShortID(id);
if (shortZoneID == null) {
continue;
}
} else if (PATTERNS[patidx].equals("VVV")) {
// This is expected behavior.
if (id.indexOf('/') < 0 || LOC_EXCLUSION_PATTERN.matcher(id).matches()) {
continue;
}
}
if (id.equals("Pacific/Apia") && PATTERNS[patidx].equals("vvvv") && logKnownIssue("11052", "Ambiguous zone name - Samoa Time")) {
continue;
}
BasicTimeZone btz = (BasicTimeZone) TimeZone.getTimeZone(id, TimeZone.TIMEZONE_ICU);
TimeZone tz = TimeZone.getTimeZone(id);
sdf.setTimeZone(tz);
long t = START_TIME;
TimeZoneTransition tzt = null;
boolean middle = true;
boolean last = false;
while (t < END_TIME) {
if (tzt == null) {
testTimes[0] = t;
expectedRoundTrip[0] = true;
testLen = 1;
} else {
int fromOffset = tzt.getFrom().getRawOffset() + tzt.getFrom().getDSTSavings();
int toOffset = tzt.getTo().getRawOffset() + tzt.getTo().getDSTSavings();
int delta = toOffset - fromOffset;
if (delta < 0) {
boolean isDstDecession = tzt.getFrom().getDSTSavings() > 0 && tzt.getTo().getDSTSavings() == 0;
testTimes[0] = t + delta - 1;
expectedRoundTrip[0] = true;
testTimes[1] = t + delta;
expectedRoundTrip[1] = isDstDecession ? !AMBIGUOUS_DST_DECESSION.contains(PATTERNS[patidx]) : !AMBIGUOUS_NEGATIVE_SHIFT.contains(PATTERNS[patidx]);
testTimes[2] = t - 1;
expectedRoundTrip[2] = isDstDecession ? !AMBIGUOUS_DST_DECESSION.contains(PATTERNS[patidx]) : !AMBIGUOUS_NEGATIVE_SHIFT.contains(PATTERNS[patidx]);
testTimes[3] = t;
expectedRoundTrip[3] = true;
testLen = 4;
} else {
testTimes[0] = t - 1;
expectedRoundTrip[0] = true;
testTimes[1] = t;
expectedRoundTrip[1] = true;
testLen = 2;
}
}
for (int testidx = 0; testidx < testLen; testidx++) {
testCounts++;
timer = System.currentTimeMillis();
String text = sdf.format(new Date(testTimes[testidx]));
try {
Date parsedDate = sdf.parse(text);
long restime = parsedDate.getTime();
long timeDiff = restime - testTimes[testidx];
boolean bTimeMatch = minutesOffset ? (timeDiff / 60000) * 60000 == 0 : timeDiff == 0;
if (!bTimeMatch) {
StringBuffer msg = new StringBuffer();
msg.append("Time round trip failed for ").append("tzid=").append(id).append(", locale=").append(LOCALES[locidx]).append(", pattern=").append(PATTERNS[patidx]).append(", text=").append(text).append(", gmt=").append(sdfGMT.format(new Date(testTimes[testidx]))).append(", time=").append(testTimes[testidx]).append(", restime=").append(restime).append(", diff=").append(timeDiff);
if (expectedRoundTrip[testidx] && !isSpecialTimeRoundTripCase(LOCALES[locidx], id, PATTERNS[patidx], testTimes[testidx])) {
errln("FAIL: " + msg.toString());
} else if (REALLY_VERBOSE_LOG) {
logln(msg.toString());
}
}
} catch (ParseException pe) {
errln("FAIL: " + pe.getMessage() + " tzid=" + id + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", text=" + text);
}
times[patidx] += System.currentTimeMillis() - timer;
}
if (last) {
break;
}
tzt = btz.getNextTransition(t, false);
if (tzt == null) {
last = true;
t = END_TIME - 1;
} else if (middle) {
// Test the date in the middle of two transitions.
t += (tzt.getTime() - t) / 2;
middle = false;
tzt = null;
} else {
t = tzt.getTime();
}
}
}
}
}
long total = 0;
logln("### Elapsed time by patterns ###");
for (int i = 0; i < PATTERNS.length; i++) {
logln(times[i] + "ms (" + PATTERNS[i] + ")");
total += times[i];
}
logln("Total: " + total + "ms");
logln("Iteration: " + testCounts);
}
use of android.icu.util.BasicTimeZone in project j2objc by google.
the class TimeZoneFormatTest method TestTimeZoneRoundTrip.
/*
* Test case for checking if a TimeZone is properly set in the result calendar
* and if the result TimeZone has the expected behavior.
*/
@Test
public void TestTimeZoneRoundTrip() {
boolean TEST_ALL = getBooleanProperty("TimeZoneRoundTripAll", false);
TimeZone unknownZone = new SimpleTimeZone(-31415, "Etc/Unknown");
int badDstOffset = -1234;
int badZoneOffset = -2345;
int[][] testDateData = { { 2007, 1, 15 }, { 2007, 6, 15 }, { 1990, 1, 15 }, { 1990, 6, 15 }, { 1960, 1, 15 }, { 1960, 6, 15 } };
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.clear();
// Set up rule equivalency test range
long low, high;
cal.set(1900, 0, 1);
low = cal.getTimeInMillis();
cal.set(2040, 0, 1);
high = cal.getTimeInMillis();
// Set up test dates
Date[] DATES = new Date[testDateData.length];
cal.clear();
for (int i = 0; i < DATES.length; i++) {
cal.set(testDateData[i][0], testDateData[i][1], testDateData[i][2]);
DATES[i] = cal.getTime();
}
// Set up test locales
ULocale[] LOCALES = null;
if (TEST_ALL || TestFmwk.getExhaustiveness() > 5) {
LOCALES = ULocale.getAvailableLocales();
} else {
LOCALES = new ULocale[] { new ULocale("en"), new ULocale("en_CA"), new ULocale("fr"), new ULocale("zh_Hant") };
}
String[] tzids;
if (JDKTZ) {
tzids = java.util.TimeZone.getAvailableIDs();
} else {
tzids = TimeZone.getAvailableIDs();
}
int[] inOffsets = new int[2];
int[] outOffsets = new int[2];
// Run the roundtrip test
for (int locidx = 0; locidx < LOCALES.length; locidx++) {
logln("Locale: " + LOCALES[locidx].toString());
String localGMTString = TimeZoneFormat.getInstance(LOCALES[locidx]).formatOffsetLocalizedGMT(0);
for (int patidx = 0; patidx < PATTERNS.length; patidx++) {
logln(" pattern: " + PATTERNS[patidx]);
SimpleDateFormat sdf = new SimpleDateFormat(PATTERNS[patidx], LOCALES[locidx]);
for (int tzidx = 0; tzidx < tzids.length; tzidx++) {
if (EXCL_TZ_PATTERN.matcher(tzids[tzidx]).matches()) {
continue;
}
TimeZone tz = TimeZone.getTimeZone(tzids[tzidx]);
for (int datidx = 0; datidx < DATES.length; datidx++) {
// Format
sdf.setTimeZone(tz);
String tzstr = sdf.format(DATES[datidx]);
// Before parse, set unknown zone to SimpleDateFormat instance
// just for making sure that it does not depends on the time zone
// originally set.
sdf.setTimeZone(unknownZone);
// Parse
ParsePosition pos = new ParsePosition(0);
Calendar outcal = Calendar.getInstance(unknownZone);
outcal.set(Calendar.DST_OFFSET, badDstOffset);
outcal.set(Calendar.ZONE_OFFSET, badZoneOffset);
sdf.parse(tzstr, outcal, pos);
// Check the result
TimeZone outtz = outcal.getTimeZone();
tz.getOffset(DATES[datidx].getTime(), false, inOffsets);
outtz.getOffset(DATES[datidx].getTime(), false, outOffsets);
if (PATTERNS[patidx].equals("V")) {
// Short zone ID - should support roundtrip for canonical CLDR IDs
String canonicalID = TimeZone.getCanonicalID(tzids[tzidx]);
if (!outtz.getID().equals(canonicalID)) {
if (outtz.getID().equals("Etc/Unknown")) {
// short zone ID and "unk" is used as the fallback
if (REALLY_VERBOSE_LOG) {
logln("Canonical round trip failed (probably as expected); tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", outtz=" + outtz.getID());
}
} else {
errln("Canonical round trip failed; tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", outtz=" + outtz.getID());
}
}
} else if (PATTERNS[patidx].equals("VV")) {
// Zone ID - full roundtrip support
if (!outtz.getID().equals(tzids[tzidx])) {
errln("Zone ID round trip failed; tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", outtz=" + outtz.getID());
}
} else if (PATTERNS[patidx].equals("VVV") || PATTERNS[patidx].equals("VVVV")) {
// Location: time zone rule must be preserved except
// zones not actually associated with a specific location.
String canonicalID = TimeZone.getCanonicalID(tzids[tzidx]);
if (canonicalID != null && !outtz.getID().equals(canonicalID)) {
// Canonical ID did not match - check the rules
boolean bFailure = false;
if ((tz instanceof BasicTimeZone) && (outtz instanceof BasicTimeZone)) {
boolean hasNoLocation = TimeZone.getRegion(tzids[tzidx]).equals("001");
bFailure = !hasNoLocation && !((BasicTimeZone) outtz).hasEquivalentTransitions(tz, low, high);
}
if (bFailure) {
errln("Canonical round trip failed; tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", outtz=" + outtz.getID());
} else if (REALLY_VERBOSE_LOG) {
logln("Canonical round trip failed (as expected); tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", outtz=" + outtz.getID());
}
}
} else {
boolean isOffsetFormat = (PATTERNS[patidx].charAt(0) == 'Z' || PATTERNS[patidx].charAt(0) == 'O' || PATTERNS[patidx].charAt(0) == 'X' || PATTERNS[patidx].charAt(0) == 'x');
boolean minutesOffset = false;
if (PATTERNS[patidx].charAt(0) == 'X' || PATTERNS[patidx].charAt(0) == 'x') {
minutesOffset = PATTERNS[patidx].length() <= 3;
}
if (!isOffsetFormat) {
// Check if localized GMT format is used as a fallback of name styles
int numDigits = 0;
for (int n = 0; n < tzstr.length(); n++) {
if (UCharacter.isDigit(tzstr.charAt(n))) {
numDigits++;
}
}
isOffsetFormat = (numDigits > 0);
}
if (isOffsetFormat || tzstr.equals(localGMTString)) {
// Localized GMT or ISO: total offset (raw + dst) must be preserved.
int inOffset = inOffsets[0] + inOffsets[1];
int outOffset = outOffsets[0] + outOffsets[1];
int diff = outOffset - inOffset;
if (minutesOffset) {
diff = (diff / 60000) * 60000;
}
if (diff != 0) {
errln("Offset round trip failed; tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", inOffset=" + inOffset + ", outOffset=" + outOffset);
}
} else {
// Specific or generic: raw offset must be preserved.
if (inOffsets[0] != outOffsets[0]) {
if (JDKTZ && tzids[tzidx].startsWith("SystemV/")) {
// ICU handles these zones as aliases of existing time zones
if (REALLY_VERBOSE_LOG) {
logln("Raw offset round trip failed; tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", inRawOffset=" + inOffsets[0] + ", outRawOffset=" + outOffsets[0]);
}
} else {
errln("Raw offset round trip failed; tz=" + tzids[tzidx] + ", locale=" + LOCALES[locidx] + ", pattern=" + PATTERNS[patidx] + ", time=" + DATES[datidx].getTime() + ", str=" + tzstr + ", inRawOffset=" + inOffsets[0] + ", outRawOffset=" + outOffsets[0]);
}
}
}
}
}
}
}
}
}
use of android.icu.util.BasicTimeZone in project Resurrection_packages_apps_Settings by ResurrectionRemix.
the class TimeZoneInfoPreferenceController method findNextDstTransition.
private TimeZoneTransition findNextDstTransition(TimeZone timeZone) {
if (!(timeZone instanceof BasicTimeZone)) {
return null;
}
final BasicTimeZone basicTimeZone = (BasicTimeZone) timeZone;
TimeZoneTransition transition = basicTimeZone.getNextTransition(mDate.getTime(), /* inclusive */
false);
do {
if (transition.getTo().getDSTSavings() != transition.getFrom().getDSTSavings()) {
break;
}
transition = basicTimeZone.getNextTransition(transition.getTime(), /*inclusive */
false);
} while (transition != null);
return transition;
}
Aggregations