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