use of android.icu.util.TimeZoneTransition in project j2objc by google.
the class TimeZoneGenericNames method formatGenericNonLocationName.
/**
* Private method to get a generic string, with fallback logics involved,
* that is,
*
* 1. If a generic non-location string is available for the zone, return it.
* 2. If a generic non-location string is associated with a meta zone and
* the zone never use daylight time around the given date, use the standard
* string (if available).
* 3. If a generic non-location string is associated with a meta zone and
* the offset at the given time is different from the preferred zone for the
* current locale, then return the generic partial location string (if available)
* 4. If a generic non-location string is not available, use generic location
* string.
*
* @param tz the requested time zone
* @param date the date
* @param type the generic name type, either LONG or SHORT
* @return the name used for a generic name type, which could be the
* generic name, or the standard name (if the zone does not observes DST
* around the date), or the partial location name.
*/
private String formatGenericNonLocationName(TimeZone tz, GenericNameType type, long date) {
assert (type == GenericNameType.LONG || type == GenericNameType.SHORT);
String tzID = ZoneMeta.getCanonicalCLDRID(tz);
if (tzID == null) {
return null;
}
// Try to get a name from time zone first
NameType nameType = (type == GenericNameType.LONG) ? NameType.LONG_GENERIC : NameType.SHORT_GENERIC;
String name = _tznames.getTimeZoneDisplayName(tzID, nameType);
if (name != null) {
return name;
}
// Try meta zone
String mzID = _tznames.getMetaZoneID(tzID, date);
if (mzID != null) {
boolean useStandard = false;
int[] offsets = { 0, 0 };
tz.getOffset(date, false, offsets);
if (offsets[1] == 0) {
useStandard = true;
// Check if the zone actually uses daylight saving time around the time
if (tz instanceof BasicTimeZone) {
BasicTimeZone btz = (BasicTimeZone) tz;
TimeZoneTransition before = btz.getPreviousTransition(date, true);
if (before != null && (date - before.getTime() < DST_CHECK_RANGE) && before.getFrom().getDSTSavings() != 0) {
useStandard = false;
} else {
TimeZoneTransition after = btz.getNextTransition(date, false);
if (after != null && (after.getTime() - date < DST_CHECK_RANGE) && after.getTo().getDSTSavings() != 0) {
useStandard = false;
}
}
} else {
// If not BasicTimeZone... only if the instance is not an ICU's implementation.
// We may get a wrong answer in edge case, but it should practically work OK.
int[] tmpOffsets = new int[2];
tz.getOffset(date - DST_CHECK_RANGE, false, tmpOffsets);
if (tmpOffsets[1] != 0) {
useStandard = false;
} else {
tz.getOffset(date + DST_CHECK_RANGE, false, tmpOffsets);
if (tmpOffsets[1] != 0) {
useStandard = false;
}
}
}
}
if (useStandard) {
NameType stdNameType = (nameType == NameType.LONG_GENERIC) ? NameType.LONG_STANDARD : NameType.SHORT_STANDARD;
String stdName = _tznames.getDisplayName(tzID, stdNameType, date);
if (stdName != null) {
name = stdName;
// TODO: revisit this issue later
// In CLDR, a same display name is used for both generic and standard
// for some meta zones in some locales. This looks like a data bugs.
// For now, we check if the standard name is different from its generic
// name below.
String mzGenericName = _tznames.getMetaZoneDisplayName(mzID, nameType);
if (stdName.equalsIgnoreCase(mzGenericName)) {
name = null;
}
}
}
if (name == null) {
// Get a name from meta zone
String mzName = _tznames.getMetaZoneDisplayName(mzID, nameType);
if (mzName != null) {
// Check if we need to use a partial location format.
// This check is done by comparing offset with the meta zone's
// golden zone at the given date.
String goldenID = _tznames.getReferenceZoneID(mzID, getTargetRegion());
if (goldenID != null && !goldenID.equals(tzID)) {
TimeZone goldenZone = TimeZone.getFrozenTimeZone(goldenID);
int[] offsets1 = { 0, 0 };
// Check offset in the golden zone with wall time.
// With getOffset(date, false, offsets1),
// you may get incorrect results because of time overlap at DST->STD
// transition.
goldenZone.getOffset(date + offsets[0] + offsets[1], true, offsets1);
if (offsets[0] != offsets1[0] || offsets[1] != offsets1[1]) {
// Now we need to use a partial location format.
name = getPartialLocationName(tzID, mzID, (nameType == NameType.LONG_GENERIC), mzName);
} else {
name = mzName;
}
} else {
name = mzName;
}
}
}
}
return name;
}
use of android.icu.util.TimeZoneTransition in project j2objc by google.
the class OlsonTimeZone method setRawOffset.
/* (non-Javadoc)
* @see android.icu.util.TimeZone#setRawOffset(int)
*/
@Override
public void setRawOffset(int offsetMillis) {
if (isFrozen()) {
throw new UnsupportedOperationException("Attempt to modify a frozen OlsonTimeZone instance.");
}
if (getRawOffset() == offsetMillis) {
return;
}
long current = System.currentTimeMillis();
if (current < finalStartMillis) {
SimpleTimeZone stz = new SimpleTimeZone(offsetMillis, getID());
boolean bDst = useDaylightTime();
if (bDst) {
TimeZoneRule[] currentRules = getSimpleTimeZoneRulesNear(current);
if (currentRules.length != 3) {
// DST was observed at the beginning of this year, so useDaylightTime
// returned true. getSimpleTimeZoneRulesNear requires at least one
// future transition for making a pair of rules. This implementation
// rolls back the time before the latest offset transition.
TimeZoneTransition tzt = getPreviousTransition(current, false);
if (tzt != null) {
currentRules = getSimpleTimeZoneRulesNear(tzt.getTime() - 1);
}
}
if (currentRules.length == 3 && (currentRules[1] instanceof AnnualTimeZoneRule) && (currentRules[2] instanceof AnnualTimeZoneRule)) {
// A pair of AnnualTimeZoneRule
AnnualTimeZoneRule r1 = (AnnualTimeZoneRule) currentRules[1];
AnnualTimeZoneRule r2 = (AnnualTimeZoneRule) currentRules[2];
DateTimeRule start, end;
int offset1 = r1.getRawOffset() + r1.getDSTSavings();
int offset2 = r2.getRawOffset() + r2.getDSTSavings();
int sav;
if (offset1 > offset2) {
start = r1.getRule();
end = r2.getRule();
sav = offset1 - offset2;
} else {
start = r2.getRule();
end = r1.getRule();
sav = offset2 - offset1;
}
// getSimpleTimeZoneRulesNear always return rules using DOW / WALL_TIME
stz.setStartRule(start.getRuleMonth(), start.getRuleWeekInMonth(), start.getRuleDayOfWeek(), start.getRuleMillisInDay());
stz.setEndRule(end.getRuleMonth(), end.getRuleWeekInMonth(), end.getRuleDayOfWeek(), end.getRuleMillisInDay());
// set DST saving amount and start year
stz.setDSTSavings(sav);
} else {
// This could only happen if last rule is DST
// and the rule used forever. For example, Asia/Dhaka
// in tzdata2009i stays in DST forever.
// Hack - set DST starting at midnight on Jan 1st,
// ending 23:59:59.999 on Dec 31st
stz.setStartRule(0, 1, 0);
stz.setEndRule(11, 31, Grego.MILLIS_PER_DAY - 1);
}
}
int[] fields = Grego.timeToFields(current, null);
finalStartYear = fields[0];
finalStartMillis = Grego.fieldsToDay(fields[0], 0, 1);
if (bDst) {
// we probably do not need to set start year of final rule
// to finalzone itself, but we always do this for now.
stz.setStartYear(finalStartYear);
}
finalZone = stz;
} else {
finalZone.setRawOffset(offsetMillis);
}
transitionRulesInitialized = false;
}
use of android.icu.util.TimeZoneTransition in project j2objc by google.
the class TimeZoneRuleTest method TestVTimeZoneCoverage.
/*
* API coverage test for VTimeZone
*/
@Test
public void TestVTimeZoneCoverage() {
final String TZID = "Europe/Moscow";
BasicTimeZone otz = (BasicTimeZone) TimeZone.getTimeZone(TZID, TimeZone.TIMEZONE_ICU);
VTimeZone vtz = VTimeZone.create(TZID);
// getOffset(era, year, month, day, dayOfWeek, milliseconds)
int offset1 = otz.getOffset(GregorianCalendar.AD, 2007, Calendar.JULY, 1, Calendar.SUNDAY, 0);
int offset2 = vtz.getOffset(GregorianCalendar.AD, 2007, Calendar.JULY, 1, Calendar.SUNDAY, 0);
if (offset1 != offset2) {
errln("FAIL: getOffset(int,int,int,int,int,int) returned different results in VTimeZone and OlsonTimeZone");
}
// getOffset(date, local, offsets)
int[] offsets1 = new int[2];
int[] offsets2 = new int[2];
long t = System.currentTimeMillis();
otz.getOffset(t, false, offsets1);
vtz.getOffset(t, false, offsets2);
if (offsets1[0] != offsets2[0] || offsets1[1] != offsets2[1]) {
errln("FAIL: getOffset(long,boolean,int[]) returned different results in VTimeZone and OlsonTimeZone");
}
// getRawOffset
if (otz.getRawOffset() != vtz.getRawOffset()) {
errln("FAIL: getRawOffset returned different results in VTimeZone and OlsonTimeZone");
}
// inDaylightTime
Date d = new Date();
if (otz.inDaylightTime(d) != vtz.inDaylightTime(d)) {
errln("FAIL: inDaylightTime returned different results in VTimeZone and OlsonTimeZone");
}
// useDaylightTime
if (otz.useDaylightTime() != vtz.useDaylightTime()) {
errln("FAIL: useDaylightTime returned different results in VTimeZone and OlsonTimeZone");
}
// setRawOffset
final int RAW = -10 * HOUR;
VTimeZone tmpvtz = (VTimeZone) vtz.clone();
tmpvtz.setRawOffset(RAW);
if (tmpvtz.getRawOffset() != RAW) {
logln("setRawOffset is implemented");
}
// hasSameRules
boolean bSame = otz.hasSameRules(vtz);
logln("OlsonTimeZone#hasSameRules(VTimeZone) should return false always for now - actual: " + bSame);
// getTZURL/setTZURL
final String TZURL = "http://icu-project.org/timezone";
String tzurl = vtz.getTZURL();
if (tzurl != null) {
errln("FAIL: getTZURL returned non-null value");
}
vtz.setTZURL(TZURL);
tzurl = vtz.getTZURL();
if (!TZURL.equals(tzurl)) {
errln("FAIL: URL returned by getTZURL does not match the one set by setTZURL");
}
// getLastModified/setLastModified
Date lastmod = vtz.getLastModified();
if (lastmod != null) {
errln("FAIL: getLastModified returned non-null value");
}
Date newdate = new Date();
vtz.setLastModified(newdate);
lastmod = vtz.getLastModified();
if (!newdate.equals(lastmod)) {
errln("FAIL: Date returned by getLastModified does not match the one set by setLastModified");
}
// getNextTransition/getPreviousTransition
long base = getUTCMillis(2007, Calendar.JULY, 1);
TimeZoneTransition tzt1 = otz.getNextTransition(base, true);
TimeZoneTransition tzt2 = vtz.getNextTransition(base, true);
if (tzt1.equals(tzt2)) {
errln("FAIL: getNextTransition returned different results in VTimeZone and OlsonTimeZone");
}
tzt1 = otz.getPreviousTransition(base, false);
tzt2 = vtz.getPreviousTransition(base, false);
if (tzt1.equals(tzt2)) {
errln("FAIL: getPreviousTransition returned different results in VTimeZone and OlsonTimeZone");
}
// hasEquivalentTransitions
long time1 = getUTCMillis(1950, Calendar.JANUARY, 1);
long time2 = getUTCMillis(2020, Calendar.JANUARY, 1);
if (!vtz.hasEquivalentTransitions(otz, time1, time2)) {
errln("FAIL: hasEquivalentTransitons returned false for the same time zone");
}
// getTimeZoneRules
TimeZoneRule[] rulesetAll = vtz.getTimeZoneRules();
TimeZoneRule[] ruleset1 = vtz.getTimeZoneRules(time1);
TimeZoneRule[] ruleset2 = vtz.getTimeZoneRules(time2);
if (rulesetAll.length < ruleset1.length || ruleset1.length < ruleset2.length) {
errln("FAIL: Number of rules returned by getRules is invalid");
}
int[] offsets_vtzc = new int[2];
VTimeZone vtzc = VTimeZone.create("PST");
vtzc.getOffsetFromLocal(Calendar.getInstance(vtzc).getTimeInMillis(), VTimeZone.LOCAL_STD, VTimeZone.LOCAL_STD, offsets_vtzc);
if (offsets_vtzc[0] > offsets_vtzc[1]) {
errln("Error getOffsetFromLocal()");
}
}
use of android.icu.util.TimeZoneTransition in project j2objc by google.
the class TimeZoneRuleTest method TestVTimeZoneRoundTrip.
/*
* Write out time zone rules of OlsonTimeZone into VTIMEZONE format, create a new
* VTimeZone from the VTIMEZONE data, then compare transitions
*/
@Test
public void TestVTimeZoneRoundTrip() {
long startTime = getUTCMillis(1850, Calendar.JANUARY, 1);
long endTime = getUTCMillis(2050, Calendar.JANUARY, 1);
String[] tzids = getTestZIDs();
for (int i = 0; i < tzids.length; i++) {
BasicTimeZone olsontz = (BasicTimeZone) TimeZone.getTimeZone(tzids[i], TimeZone.TIMEZONE_ICU);
VTimeZone vtz_org = VTimeZone.create(tzids[i]);
vtz_org.setTZURL("http://source.icu-project.org/timezone");
vtz_org.setLastModified(new Date());
VTimeZone vtz_new = null;
try {
// Write out VTIMEZONE
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(baos);
vtz_org.write(writer);
writer.close();
byte[] vtzdata = baos.toByteArray();
// Read VTIMEZONE
ByteArrayInputStream bais = new ByteArrayInputStream(vtzdata);
InputStreamReader reader = new InputStreamReader(bais);
vtz_new = VTimeZone.create(reader);
reader.close();
// Write out VTIMEZONE one more time
ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
OutputStreamWriter writer1 = new OutputStreamWriter(baos1);
vtz_new.write(writer1);
writer1.close();
byte[] vtzdata1 = baos1.toByteArray();
// Make sure VTIMEZONE data is exactly same with the first one
if (vtzdata.length != vtzdata1.length) {
errln("FAIL: different VTIMEZONE data length");
}
for (int j = 0; j < vtzdata.length; j++) {
if (vtzdata[j] != vtzdata1[j]) {
errln("FAIL: different VTIMEZONE data");
break;
}
}
} catch (IOException ioe) {
errln("FAIL: IO error while writing/reading VTIMEZONE data");
}
// VTIMEZONE.
if (vtz_new.getOffset(startTime) != olsontz.getOffset(startTime)) {
errln("FAIL: VTimeZone for " + tzids[i] + " is not equivalent to its OlsonTimeZone corresponding at " + startTime);
}
TimeZoneTransition tzt = olsontz.getNextTransition(startTime, false);
if (tzt != null) {
if (!vtz_new.hasEquivalentTransitions(olsontz, tzt.getTime(), endTime, true)) {
int maxDelta = 1000;
if (!hasEquivalentTransitions(vtz_new, olsontz, tzt.getTime() + maxDelta, endTime, true, maxDelta)) {
errln("FAIL: VTimeZone for " + tzids[i] + " is not equivalent to its OlsonTimeZone corresponding.");
} else {
logln("VTimeZone for " + tzids[i] + " differs from its OlsonTimeZone corresponding with maximum transition time delta - " + maxDelta);
}
}
if (!vtz_new.hasEquivalentTransitions(olsontz, tzt.getTime(), endTime, false)) {
logln("VTimeZone for " + tzids[i] + " is not equivalent to its OlsonTimeZone corresponding in strict comparison mode.");
}
}
}
}
use of android.icu.util.TimeZoneTransition in project j2objc by google.
the class TimeZoneRuleTest method compareTransitionsAscending.
/*
* Compare all time transitions in 2 time zones in the specified time range in ascending order
*/
private void compareTransitionsAscending(TimeZone tz1, TimeZone tz2, long start, long end, boolean inclusive) {
BasicTimeZone z1 = (BasicTimeZone) tz1;
BasicTimeZone z2 = (BasicTimeZone) tz2;
String zid1 = tz1.getID();
String zid2 = tz2.getID();
long time = start;
while (true) {
TimeZoneTransition tzt1 = z1.getNextTransition(time, inclusive);
TimeZoneTransition tzt2 = z2.getNextTransition(time, inclusive);
boolean inRange1 = false;
boolean inRange2 = false;
if (tzt1 != null) {
if (tzt1.getTime() < end || (inclusive && tzt1.getTime() == end)) {
inRange1 = true;
}
}
if (tzt2 != null) {
if (tzt2.getTime() < end || (inclusive && tzt2.getTime() == end)) {
inRange2 = true;
}
}
if (!inRange1 && !inRange2) {
// No more transition in the range
break;
}
if (!inRange1) {
errln("FAIL: " + zid1 + " does not have any transitions after " + time + " before " + end);
break;
}
if (!inRange2) {
errln("FAIL: " + zid2 + " does not have any transitions after " + time + " before " + end);
break;
}
if (tzt1.getTime() != tzt2.getTime()) {
errln("FAIL: First transition after " + time + " " + zid1 + "[" + tzt1.getTime() + "] " + zid2 + "[" + tzt2.getTime() + "]");
break;
}
time = tzt1.getTime();
if (inclusive) {
time++;
}
}
}
Aggregations