public void testTimeZoneHelperToICalendarCanberra() { TimeZoneHelper vctz = new TimeZoneHelper( "Australia/Canberra", 1167609600000L, // 01 Jan 2007 @ 00:00:00 UTC 1349049600000L); // 01 Oct 2012 @ 00:00:00 UTC VTimezone vtz = vctz.getVTimezone(); List<VComponent> dayLightComponents = vtz.getComponents("DAYLIGHT"); List<VComponent> standardComponents = vtz.getComponents("STANDARD"); assertEquals("Australia/Canberra", vtz.getProperty("TZID").getValue()); assertEquals(1, dayLightComponents.size()); TzDaylightComponent dayLight = (TzDaylightComponent) dayLightComponents.get(0); assertEquals("+1000", dayLight.getProperty("TZOFFSETFROM").getValue()); assertEquals("+1100", dayLight.getProperty("TZOFFSETTO").getValue()); assertEquals("20061029T020000", dayLight.getProperty("DTSTART").getValue()); assertEquals( "FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10", dayLight.getProperty("RRULE").getValue()); assertEquals(1, standardComponents.size()); TzStandardComponent standard = (TzStandardComponent) standardComponents.get(0); assertEquals("+1100", standard.getProperty("TZOFFSETFROM").getValue()); assertEquals("+1000", standard.getProperty("TZOFFSETTO").getValue()); assertEquals("20070325T030000", standard.getProperty("DTSTART").getValue()); assertEquals( "FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3", standard.getProperty("RRULE").getValue()); }
public void testTimeZoneHelperToICalendarBogota() { TimeZoneHelper vctz = new TimeZoneHelper( "America/Bogota", 0L, // 01 Jan 1970 @ 00:00:00 UTC 1324771200000L); // 25 Dec 2011 @ 00:00:00 UTC VTimezone vtz = vctz.getVTimezone(); List<VComponent> dayLightComponents = vtz.getComponents("DAYLIGHT"); List<VComponent> standardComponents = vtz.getComponents("STANDARD"); assertEquals("America/Bogota", vtz.getProperty("TZID").getValue()); assertEquals(0, dayLightComponents.size()); assertEquals(2, standardComponents.size()); TzStandardComponent standard = (TzStandardComponent) standardComponents.get(0); assertEquals("-0500", standard.getProperty("TZOFFSETFROM").getValue()); assertEquals("-0400", standard.getProperty("TZOFFSETTO").getValue()); assertEquals("19920503T000000", standard.getProperty("DTSTART").getValue()); assertEquals("19920503T000000", standard.getProperty("RDATE").getValue()); standard = (TzStandardComponent) standardComponents.get(1); assertEquals("-0400", standard.getProperty("TZOFFSETFROM").getValue()); assertEquals("-0500", standard.getProperty("TZOFFSETTO").getValue()); assertEquals("19930404T000000", standard.getProperty("DTSTART").getValue()); assertEquals("19930404T000000", standard.getProperty("RDATE").getValue()); }
public void testTimeZoneHelperFromICalendarBerlinUntil() throws Exception { VTimezone vtz = new VTimezone(); vtz.addProperty("TZID", "Berlino"); // No hint TzStandardComponent standardC = new TzStandardComponent(); standardC.addProperty("TZOFFSETFROM", "+0200"); standardC.addProperty("TZOFFSETTO", "+0100"); standardC.addProperty("TZNAME", "CET"); standardC.addProperty("DTSTART", "19701025T030000"); standardC.addProperty( "RRULE", "FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10;UNTIL=20091231T000113Z"); TzDaylightComponent dayLightC = new TzDaylightComponent(); dayLightC.addProperty("TZOFFSETFROM", "+0100"); dayLightC.addProperty("TZOFFSETTO", "+0200"); dayLightC.addProperty("TZNAME", "CEST"); dayLightC.addProperty("DTSTART", "19700329T020000"); dayLightC.addProperty( "RRULE", "FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3;UNTIL=20091231T000113Z"); vtz.addStandardc(standardC); vtz.addDaylightc(dayLightC); TimeZoneHelper vctz = new TimeZoneHelper( vtz, 1167609600000L, // 01 Jan 2007 @ 00:00:00 UTC 1324771200000L); // 25 Dec 2011 @ 00:00:00 UTC List<TimeZoneTransition> transitions = vctz.getTransitions(); assertEquals("Berlino", vctz.getName()); assertEquals(6, transitions.size()); assertEquals(3600000, vctz.getBasicOffset()); boolean dst = true; for (TimeZoneTransition transition : transitions) { if (dst) { assertEquals("CEST", transition.getName()); } else { assertEquals("CET", transition.getName()); } dst = !dst; } assertEquals(7200000, transitions.get(0).getOffset()); assertEquals(1174784400000L, transitions.get(0).getTime()); assertEquals(3600000, transitions.get(1).getOffset()); assertEquals(1193533200000L, transitions.get(1).getTime()); assertEquals(7200000, transitions.get(2).getOffset()); assertEquals(1206838800000L, transitions.get(2).getTime()); assertEquals(3600000, transitions.get(3).getOffset()); assertEquals(1224982800000L, transitions.get(3).getTime()); assertEquals(7200000, transitions.get(4).getOffset()); assertEquals(1238288400000L, transitions.get(4).getTime()); assertEquals(3600000, transitions.get(5).getOffset()); assertEquals(1256432400000L, transitions.get(5).getTime()); assertEquals("Europe/Berlin", vctz.toID()); // First run assertEquals("Europe/Berlin", vctz.toID()); // Second run (cached) }
@SuppressWarnings("unchecked") public void testTimeZoneHelperCheckAllOlsonIDsWithICalendar() throws Exception { int mistakes = 0; // counter for mistakes in time zone handling /* * Max number of mistakes allowed. This value should be lowered as soon * as improvements in the code that handles time zones reduce the * number of mistakes. In this way, this test can be used to certify * that the number of properly handled time zones is being constantly * raised. */ final int MAX_MISTAKES = 125; System.out.println("================================= iCalendar (2.0)"); for (String id : (Set<String>) DateTimeZone.getAvailableIDs()) { TimeZoneHelper vctzOut = new TimeZoneHelper( id, // 0L, // 01 Jan 1970 @ 00:00:00 UTC 915148800000L, // 01 Jan 1999 @ 00:00:00 UTC 1324771200000L); // 25 Dec 2011 @ 00:00:00 UTC VTimezone vTimezone = vctzOut.getVTimezone(); // Uncomment this to debug the iCalendar items referring to one // continent: /* String continent = "Australia"; // or whatever you want to watch if (id.startsWith(continent)) { System.out.println("\n\n" + vTimezone); } */ vTimezone.getProperty("TZID").setValue(""); // The name should not be used as a hint for // this "test" TimeZoneHelper vctzIn = new TimeZoneHelper( vTimezone, 915148800000L, // 01 Jan 1999 @ 00:00:00 UTC 1324771200000L); // 25 Dec 2011 @ 00:00:00 UTC System.out.print('\n' + id + " --> " + vctzIn.toID()); vctzIn.clearCachedID(); String guess = vctzIn.toID(id); if (!id.equals(guess)) { System.out.print(" (WRONG!)"); mistakes++; } } System.out.println("\n\n" + mistakes + " time zones were not properly handled."); assertTrue(mistakes <= MAX_MISTAKES); System.out.println(); }
/** * Creates a new instance of TimeZoneHelper on the basis of the information extracted from an * iCalendar (vCalendar 2.0) item. * * @param vTimeZone * @param from the start of the relevant time interval for the generation of transitions (an * istant expressed as a long) * @param to the end of the relevant time interval for the generation of transitions (an istant * expressed as a long) * @throws java.lang.Exception */ public TimeZoneHelper(VTimezone vTimeZone, long from, long to) throws Exception { setFormattersToUTC(); Property tzID = vTimeZone.getProperty("TZID"); if (tzID != null) { this.name = tzID.getValue(); // Try and skip the parsing by using just the TZID: String extracted = extractID(name); if (extracted != null) { cacheID(extracted); processID(extracted, from, to); return; } List<VComponent> standardTimeRules = vTimeZone.getComponents("STANDARD"); List<VComponent> summerTimeRules = vTimeZone.getComponents("DAYLIGHT"); String standardTimeOffset; if (standardTimeRules.isEmpty()) { if (summerTimeRules.isEmpty()) { throw new Exception("Empty VTIMEZONE"); } else { standardTimeOffset = summerTimeRules.get(0).getProperty("TZOFFSETFROM").getValue(); } } else { standardTimeOffset = standardTimeRules.get(0).getProperty("TZOFFSETTO").getValue(); } basicOffset = parseOffset(standardTimeOffset); for (VComponent standardTimeRule : standardTimeRules) { addTransitions(standardTimeRule, from, to); } for (VComponent summerTimeRule : summerTimeRules) { addTransitions(summerTimeRule, from, to); } Collections.sort(transitions); } else { this.name = ""; // This should not happen! } }
public void testTimeZoneHelperToICalendarJohannesburg() { TimeZoneHelper vctz = new TimeZoneHelper( "Africa/Johannesburg", 0L, // 01 Jan 1970 @ 00:00:00 UTC 1324771200000L); // 25 Dec 2011 @ 00:00:00 UTC VTimezone vtz = vctz.getVTimezone(); List<VComponent> dayLightComponents = vtz.getComponents("DAYLIGHT"); List<VComponent> standardComponents = vtz.getComponents("STANDARD"); assertEquals("Africa/Johannesburg", vtz.getProperty("TZID").getValue()); assertEquals(0, dayLightComponents.size()); assertEquals(1, standardComponents.size()); TzStandardComponent standard = (TzStandardComponent) standardComponents.get(0); assertEquals("+0200", standard.getProperty("TZOFFSETFROM").getValue()); assertEquals("+0200", standard.getProperty("TZOFFSETTO").getValue()); assertEquals("19700101T000000", standard.getProperty("DTSTART").getValue()); assertEquals("19700101T000000", standard.getProperty("RDATE").getValue()); }
protected static VTimezone toVTimezone( List<ICalendarTimeZoneTransition> iCalendarTransitions, String id, int basicOffset) { VTimezone vtz = new VTimezone(); vtz.addProperty("TZID", id); TzDaylightComponent summerTimeRDates = null; TzStandardComponent standardTimeRDates = null; String standardTimeOffset = formatOffset(basicOffset); // Visits all transitions in cronological order for (int i = 0; i < iCalendarTransitions.size(); ) { // If it's the last transition, or it's a transition that is not // part of the standard/day-light time series, the special case must // be separately treated if ((i == iCalendarTransitions.size() - 1) || (!areHalfYearFar( iCalendarTransitions.get(i).getTime(), iCalendarTransitions.get(i + 1).getTime()))) { // "Burns" components that may be present in the buffer if (summerTimeRDates != null) { vtz.addComponent(summerTimeRDates); vtz.addComponent(standardTimeRDates); summerTimeRDates = null; standardTimeRDates = null; } // Creates a new STANDARD component of the RDATE kind TzStandardComponent specialRDate = new TzStandardComponent(); String specialCaseTime = iCalendarTransitions.get(i).getTimeISO1861(); specialRDate.addProperty("DTSTART", specialCaseTime); specialRDate.addProperty("RDATE", specialCaseTime); specialRDate.addProperty("TZOFFSETFROM", standardTimeOffset); standardTimeOffset = // It needs be updated formatOffset(iCalendarTransitions.get(i).getOffset()); specialRDate.addProperty("TZOFFSETTO", standardTimeOffset); specialRDate.addProperty("TZNAME", iCalendarTransitions.get(i).getName()); vtz.addComponent(specialRDate); // Burns it i++; // Moves on to the next transition continue; } String lastOffset = standardTimeOffset; String summerTimeOffset = formatOffset(iCalendarTransitions.get(i).getOffset()); standardTimeOffset = formatOffset(iCalendarTransitions.get(i + 1).getOffset()); String summerTimeStart = iCalendarTransitions.get(i).getTimeISO1861(); String standardTimeStart = iCalendarTransitions.get(i + 1).getTimeISO1861(); ICalendarTimeZoneTransition summerTimeClusterStart = iCalendarTransitions.get(i); ICalendarTimeZoneTransition standardTimeClusterStart = iCalendarTransitions.get(i + 1); int j; // Summer-time starts, backward instance count int k; // Summer-time starts, forward instance count int l; // Summer-time ends, backward instance count int m; // Summer-time ends, forward instance count for (j = i + 2; j < iCalendarTransitions.size(); j += 2) { ICalendarTimeZoneTransition clusterMember = iCalendarTransitions.get(j); if (!summerTimeClusterStart.matchesRecurrence(clusterMember, true)) { break; } } for (k = i + 2; k < iCalendarTransitions.size(); k += 2) { ICalendarTimeZoneTransition clusterMember = iCalendarTransitions.get(k); if (!summerTimeClusterStart.matchesRecurrence(clusterMember, false)) { break; } } for (l = i + 3; l < iCalendarTransitions.size(); l += 2) { ICalendarTimeZoneTransition clusterMember = iCalendarTransitions.get(l); if (!standardTimeClusterStart.matchesRecurrence(clusterMember, true)) { break; } } for (m = i + 3; m < iCalendarTransitions.size(); m += 2) { ICalendarTimeZoneTransition clusterMember = iCalendarTransitions.get(m); if (!standardTimeClusterStart.matchesRecurrence(clusterMember, false)) { break; } } boolean backwardInstanceCountForStarts = true; boolean backwardInstanceCountForEnds = true; if (k > j) { // counting istances in the forward direction makes a // longer summer-time-start series j = k; // j is now the longest series of summer-time starts backwardInstanceCountForStarts = false; } if (m > l) { // counting istances in the forward direction makes a // longer summer-time-end series l = m; // l is now the longest series of summer-time ends backwardInstanceCountForEnds = false; } j -= 2; // Compensates for the end condition of the for cycle above l -= 2; // Compensates for the end condition of the for cycle above if (l > j + 1) { l = j + 1; // l is now the best acceptable end for a // combined start-end series } else { j = l - 1; } // At this point, l + 1 = j if (l > i + 1) { // more than one year: there's a recurrence if (summerTimeRDates != null) { vtz.addComponent(summerTimeRDates); vtz.addComponent(standardTimeRDates); } // Create a new DAYLIGHT component summerTimeRDates = new TzDaylightComponent(); summerTimeRDates.addProperty("DTSTART", summerTimeStart); StringBuffer summerTimeRRule = new StringBuffer("FREQ=YEARLY;INTERVAL=1;BYDAY="); if (backwardInstanceCountForStarts) { summerTimeRRule.append("-1"); } else { summerTimeRRule.append('+').append(summerTimeClusterStart.getInstance()); } summerTimeRRule .append(getDayOfWeekAbbreviation(summerTimeClusterStart.getDayOfWeek())) .append(";BYMONTH=") .append(summerTimeClusterStart.getMonth() + 1); // Jan must be 1 if (j < iCalendarTransitions.size() - 2) { summerTimeRRule.append(";UNTIL=").append(iCalendarTransitions.get(j).getTimeISO1861()); } summerTimeRDates.addProperty("RRULE", summerTimeRRule.toString()); summerTimeRDates.addProperty("TZOFFSETFROM", lastOffset); summerTimeRDates.addProperty("TZOFFSETTO", summerTimeOffset); summerTimeRDates.addProperty("TZNAME", iCalendarTransitions.get(i).getName()); // Create a new STANDARD component standardTimeRDates = new TzStandardComponent(); standardTimeRDates.addProperty("DTSTART", standardTimeStart); StringBuffer standardTimeRRule = new StringBuffer("FREQ=YEARLY;INTERVAL=1;BYDAY="); if (backwardInstanceCountForEnds) { standardTimeRRule.append("-1"); } else { standardTimeRRule.append('+').append(standardTimeClusterStart.getInstance()); } standardTimeRRule .append(getDayOfWeekAbbreviation(standardTimeClusterStart.getDayOfWeek())) .append(";BYMONTH=") .append(standardTimeClusterStart.getMonth() + 1); // Jan must be 1 if (l < iCalendarTransitions.size() - 1) { standardTimeRRule.append(";UNTIL=").append(iCalendarTransitions.get(l).getTimeISO1861()); } standardTimeRDates.addProperty("RRULE", standardTimeRRule.toString()); standardTimeRDates.addProperty("TZOFFSETFROM", summerTimeOffset); standardTimeRDates.addProperty("TZOFFSETTO", standardTimeOffset); standardTimeRDates.addProperty("TZNAME", iCalendarTransitions.get(i + 1).getName()); vtz.addComponent(summerTimeRDates); vtz.addComponent(standardTimeRDates); summerTimeRDates = null; standardTimeRDates = null; i = j; // Increases the counter to jump beyond the recurrence } else { // just one year: i, i+1 are transitions of the RDATE kind if (summerTimeRDates == null) { // Create a new DAYLIGHT component summerTimeRDates = new TzDaylightComponent(); summerTimeRDates.addProperty("DTSTART", summerTimeStart); summerTimeRDates.addProperty("RDATE", summerTimeStart); summerTimeRDates.addProperty("TZOFFSETFROM", lastOffset); summerTimeRDates.addProperty("TZOFFSETTO", summerTimeOffset); summerTimeRDates.addProperty("TZNAME", iCalendarTransitions.get(i).getName()); // Create a new STANDARD component standardTimeRDates = new TzStandardComponent(); standardTimeRDates.addProperty("DTSTART", standardTimeStart); standardTimeRDates.addProperty("RDATE", standardTimeStart); standardTimeRDates.addProperty("TZOFFSETFROM", summerTimeOffset); standardTimeRDates.addProperty("TZOFFSETTO", standardTimeOffset); standardTimeRDates.addProperty("TZNAME", iCalendarTransitions.get(i + 1).getName()); } else { Property rdate = summerTimeRDates.getProperty("RDATE"); rdate.setValue(rdate.getValue() + ';' + summerTimeStart); summerTimeRDates.setProperty(rdate); rdate = standardTimeRDates.getProperty("RDATE"); rdate.setValue(rdate.getValue() + ';' + standardTimeStart); standardTimeRDates.setProperty(rdate); } } i += 2; } if (summerTimeRDates != null) { vtz.addComponent(summerTimeRDates); vtz.addComponent(standardTimeRDates); summerTimeRDates = null; standardTimeRDates = null; } return vtz; }