public String getSIF() { StringBuffer xml = new StringBuffer(); List<Property> xvCalendarProperties = getXVCalendarProperties(); openXMLTag(xml, SIFCalendar.TIME_ZONE); for (Property property : xvCalendarProperties) { if ("TZ".equals(property.getName())) { addXMLNode(xml, SIFCalendar.TIME_ZONE_BASIC_OFFSET, property.getValue()); } if ("DAYLIGHT".equals(property.getName())) { String dl = property.getValue(); if (!"FALSE".equalsIgnoreCase(dl)) { openXMLTag(xml, SIFCalendar.TIME_ZONE_DAYLIGHT); String[] dlParts = dl.split(";"); addXMLNode(xml, SIFCalendar.TIME_ZONE_DST_OFFSET, dlParts[1]); addXMLNode(xml, SIFCalendar.TIME_ZONE_DST_START, dlParts[2]); addXMLNode(xml, SIFCalendar.TIME_ZONE_DST_END, dlParts[3]); addXMLNode(xml, SIFCalendar.TIME_ZONE_DST_NAME, (dlParts[4] == null) ? "" : dlParts[4]); addXMLNode( xml, SIFCalendar.TIME_ZONE_STANDARD_NAME, (dlParts[5] == null) ? "" : dlParts[5]); closeXMLTag(xml, SIFCalendar.TIME_ZONE_DAYLIGHT); } else { // When DAYLIGHT is FALSE does not send <DayLight/> } } } closeXMLTag(xml, SIFCalendar.TIME_ZONE); return xml.toString(); }
public void testTimeZoneHelperToXVCalendarBogota() { TimeZoneHelper vctz = new TimeZoneHelper( "America/Bogota", 1167609600000L, // 01 Jan 2007 @ 00:00:00 UTC 1349049600000L); // 01 Oct 2012 @ 00:00:00 UTC Property tz = vctz.getTZ(); List<Property> dayLightList = vctz.getDaylightList(); assertEquals(1, dayLightList.size()); assertEquals("TZ", tz.getName()); assertEquals("-0500", tz.getValue()); assertEquals("DAYLIGHT", dayLightList.get(0).getName()); assertEquals("FALSE", dayLightList.get(0).getValue()); }
/** * Creates a new instance of TimeZoneHelper on the basis of the information extracted from a * vCalendar (1.0) item. * * @param tz the TZ property * @param daylightList a List containing all DAYLIGHT properties * @throws java.lang.Exception */ public TimeZoneHelper(Property tz, List<Property> daylightList) throws Exception { setFormattersToUTC(); this.name = ""; // vCalendar (1.0) has no time zone identifier because // there's just one time zone per calendar item if ((tz == null) || (tz.getValue() == null) || (tz.getValue().length() == 0)) { throw new Exception("No TZ property"); } basicOffset = parseOffset(tz.getValue()); for (Property transition : daylightList) { if (transition.getValue() == null) { continue; } if (transition.getValue().startsWith("TRUE;")) { String[] daylight = transition.getValue().split(";"); String summerOffsetString = daylight[1].replaceAll("[\\+\\-:]", "") + "00"; int summerOffset = 3600000 * Integer.parseInt(summerOffsetString.substring(0, 2)); summerOffset += 60000 * Integer.parseInt(summerOffsetString.substring(2, 4)); if (daylight[1].startsWith("-")) { summerOffset = -summerOffset; } long summerStart = parseDateTime(daylight[2]); String summerTimeName; if (daylight.length >= 5) { summerTimeName = daylight[4]; } else { summerTimeName = ""; } TimeZoneTransition summerTime = new TimeZoneTransition(summerOffset, summerStart, summerTimeName); long summerEnd = parseDateTime(daylight[3]); String standardTimeName; if (daylight.length >= 6) { standardTimeName = daylight[5]; } else { standardTimeName = ""; } TimeZoneTransition standardTime = new TimeZoneTransition(basicOffset, summerEnd, standardTimeName); transitions.add(summerTime); transitions.add(standardTime); } } }
/** * 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 testTimeZoneHelperToXVCalendarCanberra() { TimeZoneHelper vctz = new TimeZoneHelper( "Australia/Canberra", 1167609600000L, // 01 Jan 2007 @ 00:00:00 UTC 1349049600000L); // 01 Oct 2012 @ 00:00:00 UTC Property tz = vctz.getTZ(); List<Property> dayLightList = vctz.getDaylightList(); assertEquals(6, dayLightList.size()); assertEquals("TZ", tz.getName()); assertEquals("+1000", tz.getValue()); assertEquals("DAYLIGHT", dayLightList.get(0).getName()); assertEquals( "TRUE;+1100;20061029T020000;20070325T030000;Australia/Canberra;Australia/Canberra", dayLightList.get(0).getValue()); assertEquals("DAYLIGHT", dayLightList.get(1).getName()); assertEquals( "TRUE;+1100;20071028T020000;20080330T030000;Australia/Canberra;Australia/Canberra", dayLightList.get(1).getValue()); assertEquals("DAYLIGHT", dayLightList.get(2).getName()); assertEquals( "TRUE;+1100;20081026T020000;20090329T030000;Australia/Canberra;Australia/Canberra", dayLightList.get(2).getValue()); assertEquals("DAYLIGHT", dayLightList.get(3).getName()); assertEquals( "TRUE;+1100;20091025T020000;20100328T030000;Australia/Canberra;Australia/Canberra", dayLightList.get(3).getValue()); assertEquals("DAYLIGHT", dayLightList.get(4).getName()); assertEquals( "TRUE;+1100;20101031T020000;20110327T030000;Australia/Canberra;Australia/Canberra", dayLightList.get(4).getValue()); assertEquals("DAYLIGHT", dayLightList.get(5).getName()); assertEquals( "TRUE;+1100;20111030T020000;20120325T030000;Australia/Canberra;Australia/Canberra", dayLightList.get(5).getValue()); }
private void addTransitions(VComponent timeRule, long from, long to) throws Exception { int offset; int previousOffset; String start; long startTime; long time; String transitionName; Property tzName = timeRule.getProperty("TZNAME"); Property tzOffsetFrom = timeRule.getProperty("TZOFFSETFROM"); Property tzOffsetTo = timeRule.getProperty("TZOFFSETTO"); Property tzDtStart = timeRule.getProperty("DTSTART"); Property tzRRule = timeRule.getProperty("RRULE"); Property tzRDate = timeRule.getProperty("RDATE"); if (tzDtStart != null) { start = tzDtStart.getValue(); startTime = parseDateTime(start); } else { throw new Exception("Required property DTSTART (of a time zone) is missing"); } if (tzOffsetTo != null) { offset = parseOffset(tzOffsetTo.getValue()); } else { throw new Exception("Required property TZOFFSETTO is missing"); } if (tzOffsetFrom != null) { previousOffset = parseOffset(tzOffsetFrom.getValue()); } else { throw new Exception("Required property TZOFFSETFROM is missing"); } if (tzName != null) { transitionName = tzName.getValue(); } else { transitionName = ""; } if (tzRDate != null) { String[] rDates = tzRDate.getValue().split(","); for (String rDate : rDates) { time = parseDateTime(rDate); transitions.add(new TimeZoneTransition(offset, time, transitionName)); } } if (tzRRule != null) { RecurrencePattern rrule = VCalendarContentConverter.getRecurrencePattern( start, null, tzRRule.getValue(), null, // as of specs false); // iCalendar if (((rrule.getTypeId() == RecurrencePattern.TYPE_MONTH_NTH) && (rrule.getInterval() == 12)) || ((rrule.getTypeId() == RecurrencePattern.TYPE_YEAR_NTH) && (rrule.getInterval() == 1))) { // yearly int dayOfWeek = getDayOfWeekFromMask(rrule.getDayOfWeekMask()); if (dayOfWeek > 0) { // one day TimeZone fixed = TimeZone.getTimeZone("UTC"); fixed.setRawOffset(previousOffset); Calendar finder = new GregorianCalendar(fixed); finder.setTimeInMillis(startTime); // Sets hour and minutes int hh = finder.get(Calendar.HOUR_OF_DAY); int mm = finder.get(Calendar.MINUTE); int m = rrule.getMonthOfYear() - 1; // Yes, it works int yearStart = year(startTime); int yearFrom = (startTime > from) ? yearStart : year(from); int yearTo = year(to); if (rrule.isNoEndDate()) { int count = rrule.getOccurrences(); int yearRecurrenceEnd; if (count != -1) { yearRecurrenceEnd = yearStart + count - 1; if (yearRecurrenceEnd < yearTo) { yearTo = yearRecurrenceEnd; } } } else { try { int yearRecurrenceEnd = year(rrule.getEndDatePattern()); if (yearRecurrenceEnd < yearTo) { yearTo = yearRecurrenceEnd; } } catch (ParseException e) { // Ignores the UNTIL part } } for (int y = yearFrom; y <= yearTo; y++) { finder.clear(); finder.set(Calendar.YEAR, y); finder.set(Calendar.MONTH, m); finder.set(Calendar.DAY_OF_WEEK, dayOfWeek); finder.set(Calendar.DAY_OF_WEEK_IN_MONTH, rrule.getInstance()); finder.set(Calendar.HOUR_OF_DAY, hh); finder.set(Calendar.MINUTE, mm); long transitionTime = finder.getTimeInMillis() - (previousOffset - getBasicOffset()); transitions.add(new TimeZoneTransition(offset, transitionTime, transitionName)); } } } } }
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; }