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()); }
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; }