{"version":3,"sources":["jsdelivr-header.js","/npm/ical.js@1.0.0/build/ical.js"],"names":[],"mappings":"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","file":"/npm/ical.js@1.0.0/build/ical.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.37.0.\n * Original file: /npm/ical.js@1.0.0/build/ical.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2011-2012 */\n\n/* istanbul ignore next */\n/* jshint ignore:start */\nif (typeof ICAL === 'undefined') {\n  if (typeof exports === 'object') {\n    // CommonJS\n    ICAL = exports;\n  } else if (typeof window !== 'undefined') {\n    // Browser globals\n    this.ICAL = {};\n  } else {\n    // ...?\n    ICAL = {};\n  }\n}\n/* jshint ignore:end */\n\nICAL.foldLength = 75;\nICAL.newLineChar = '\\r\\n';\n\n\n/**\n * Helper functions used in various places within ical.js\n */\nICAL.helpers = {\n  /**\n   * Checks if the given number is NaN\n   */\n  isStrictlyNaN: function(number) {\n    return typeof(number) === 'number' && isNaN(number);\n  },\n\n  /**\n   * Parses a string value that is expected to be an\n   * integer, when the valid is not an integer throws\n   * a decoration error.\n   *\n   * @param {String} string raw input.\n   * @return {Number} integer.\n   */\n  strictParseInt: function(string) {\n    var result = parseInt(string, 10);\n\n    if (ICAL.helpers.isStrictlyNaN(result)) {\n      throw new Error(\n        'Could not extract integer from \"' + string + '\"'\n      );\n    }\n\n    return result;\n  },\n\n  /**\n   * Creates or returns a class instance\n   * of a given type with the initialization\n   * data if the data is not already an instance\n   * of the given type.\n   *\n   *\n   * Example:\n   *\n   *    var time = new ICAL.Time(...);\n   *    var result = ICAL.helpers.formatClassType(time, ICAL.Time);\n   *\n   *    (result instanceof ICAL.Time)\n   *    // => true\n   *\n   *    result = ICAL.helpers.formatClassType({}, ICAL.Time);\n   *    (result isntanceof ICAL.Time)\n   *    // => true\n   *\n   *\n   * @param {Object} data object initialization data.\n   * @param {Object} type object type (like ICAL.Time).\n   */\n  formatClassType: function formatClassType(data, type) {\n    if (typeof(data) === 'undefined')\n      return undefined;\n\n    if (data instanceof type) {\n      return data;\n    }\n    return new type(data);\n  },\n\n  /**\n   * Identical to index of but will only match values\n   * when they are not preceded by a backslash char \\\\\\\n   *\n   * @param {String} buffer string value.\n   * @param {String} search value.\n   * @param {Numeric} pos start position.\n   */\n  unescapedIndexOf: function(buffer, search, pos) {\n    while ((pos = buffer.indexOf(search, pos)) !== -1) {\n      if (pos > 0 && buffer[pos - 1] === '\\\\') {\n        pos += 1;\n      } else {\n        return pos;\n      }\n    }\n    return -1;\n  },\n\n  binsearchInsert: function(list, seekVal, cmpfunc) {\n    if (!list.length)\n      return 0;\n\n    var low = 0, high = list.length - 1,\n        mid, cmpval;\n\n    while (low <= high) {\n      mid = low + Math.floor((high - low) / 2);\n      cmpval = cmpfunc(seekVal, list[mid]);\n\n      if (cmpval < 0)\n        high = mid - 1;\n      else if (cmpval > 0)\n        low = mid + 1;\n      else\n        break;\n    }\n\n    if (cmpval < 0)\n      return mid; // insertion is displacing, so use mid outright.\n    else if (cmpval > 0)\n      return mid + 1;\n    else\n      return mid;\n  },\n\n  dumpn: /* istanbul ignore next */ function() {\n    if (!ICAL.debug) {\n      return null;\n    }\n\n    if (typeof (console) !== 'undefined' && 'log' in console) {\n      ICAL.helpers.dumpn = function consoleDumpn(input) {\n        return console.log(input);\n      };\n    } else {\n      ICAL.helpers.dumpn = function geckoDumpn(input) {\n        dump(input + '\\n');\n      };\n    }\n\n    return ICAL.helpers.dumpn(arguments[0]);\n  },\n\n  clone: function(aSrc, aDeep) {\n    if (!aSrc || typeof aSrc != \"object\") {\n      return aSrc;\n    } else if (aSrc instanceof Date) {\n      return new Date(aSrc.getTime());\n    } else if (\"clone\" in aSrc) {\n      return aSrc.clone();\n    } else if (Array.isArray(aSrc)) {\n      var arr = [];\n      for (var i = 0; i < aSrc.length; i++) {\n        arr.push(aDeep ? ICAL.helpers.clone(aSrc[i], true) : aSrc[i]);\n      }\n      return arr;\n    } else {\n      var obj = {};\n      for (var name in aSrc) {\n        // uses prototype method to allow use of Object.create(null);\n        /* istanbul ignore else */\n        if (Object.prototype.hasOwnProperty.call(aSrc, name)) {\n          if (aDeep) {\n            obj[name] = ICAL.helpers.clone(aSrc[name], true);\n          } else {\n            obj[name] = aSrc[name];\n          }\n        }\n      }\n      return obj;\n    }\n  },\n\n  foldline: function foldline(aLine) {\n    var result = \"\";\n    var line = aLine || \"\";\n\n    while (line.length) {\n      result += ICAL.newLineChar + \" \" + line.substr(0, ICAL.foldLength);\n      line = line.substr(ICAL.foldLength);\n    }\n    return result.substr(ICAL.newLineChar.length + 1);\n  },\n\n  pad2: function pad(data) {\n    if (typeof(data) !== 'string') {\n      // handle fractions.\n      if (typeof(data) === 'number') {\n        data = parseInt(data);\n      }\n      data = String(data);\n    }\n\n    var len = data.length;\n\n    switch (len) {\n      case 0:\n        return '00';\n      case 1:\n        return '0' + data;\n      default:\n        return data;\n    }\n  },\n\n  trunc: function trunc(number) {\n    return (number < 0 ? Math.ceil(number) : Math.floor(number));\n  }\n};\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2011-2012 */\n\n/* istanbul ignore next */\n(typeof(ICAL) === 'undefined') ? ICAL = {} : ''; // jshint ignore:line\n\nICAL.design = (function() {\n  'use strict';\n\n  var ICAL_NEWLINE = /\\\\\\\\|\\\\;|\\\\,|\\\\[Nn]/g;\n\n  // default types used multiple times\n  var DEFAULT_TYPE_TEXT = { defaultType: \"text\" };\n  var DEFAULT_TYPE_TEXT_MULTI = { defaultType: \"text\", multiValue: \",\" };\n  var DEFAULT_TYPE_TEXT_STRUCTURED = { defaultType: \"text\", structuredValue: \";\" };\n  var DEFAULT_TYPE_INTEGER = { defaultType: \"integer\" };\n  var DEFAULT_TYPE_DATETIME_DATE = { defaultType: \"date-time\", allowedTypes: [\"date-time\", \"date\"] };\n  var DEFAULT_TYPE_DATETIME = { defaultType: \"date-time\" };\n  var DEFAULT_TYPE_URI = { defaultType: \"uri\" };\n  var DEFAULT_TYPE_UTCOFFSET = { defaultType: \"utc-offset\" };\n  var DEFAULT_TYPE_RECUR = { defaultType: \"recur\" };\n  var DEFAULT_TYPE_DATE_ANDOR_TIME = { defaultType: \"date-and-or-time\", allowedTypes: [\"date-time\", \"date\", \"text\"] };\n\n  function replaceNewlineReplace(string) {\n    switch (string) {\n      case \"\\\\\\\\\":\n        return \"\\\\\";\n      case \"\\\\;\":\n        return \";\";\n      case \"\\\\,\":\n        return \",\";\n      case \"\\\\n\":\n      case \"\\\\N\":\n        return \"\\n\";\n      /* istanbul ignore next */\n      default:\n        return string;\n    }\n  }\n\n  function replaceNewline(value) {\n    // avoid regex when possible.\n    if (value.indexOf('\\\\') === -1) {\n      return value;\n    }\n\n    return value.replace(ICAL_NEWLINE, replaceNewlineReplace);\n  }\n\n  var commonProperties = {\n    \"categories\": DEFAULT_TYPE_TEXT_MULTI,\n    \"url\": DEFAULT_TYPE_URI,\n    \"version\": DEFAULT_TYPE_TEXT,\n    \"uid\": DEFAULT_TYPE_TEXT\n  };\n\n  var commonValues = {\n    \"boolean\": {\n      values: [\"TRUE\", \"FALSE\"],\n\n      fromICAL: function(aValue) {\n        switch (aValue) {\n          case 'TRUE':\n            return true;\n          case 'FALSE':\n            return false;\n          default:\n            //TODO: parser warning\n            return false;\n        }\n      },\n\n      toICAL: function(aValue) {\n        if (aValue) {\n          return 'TRUE';\n        }\n        return 'FALSE';\n      }\n\n    },\n    float: {\n      matches: /^[+-]?\\d+\\.\\d+$/,\n\n      fromICAL: function(aValue) {\n        var parsed = parseFloat(aValue);\n        if (ICAL.helpers.isStrictlyNaN(parsed)) {\n          // TODO: parser warning\n          return 0.0;\n        }\n        return parsed;\n      },\n\n      toICAL: function(aValue) {\n        return String(aValue);\n      }\n    },\n    integer: {\n      fromICAL: function(aValue) {\n        var parsed = parseInt(aValue);\n        if (ICAL.helpers.isStrictlyNaN(parsed)) {\n          return 0;\n        }\n        return parsed;\n      },\n\n      toICAL: function(aValue) {\n        return String(aValue);\n      }\n    },\n    text: {\n      matches: /.*/,\n\n      fromICAL: function(aValue, aName) {\n        return replaceNewline(aValue);\n      },\n\n      toICAL: function escape(aValue, aName) {\n        return aValue.replace(/\\\\|;|,|\\n/g, function(str) {\n          switch (str) {\n          case \"\\\\\":\n            return \"\\\\\\\\\";\n          case \";\":\n            return \"\\\\;\";\n          case \",\":\n            return \"\\\\,\";\n          case \"\\n\":\n            return \"\\\\n\";\n          /* istanbul ignore next */\n          default:\n            return str;\n          }\n        });\n      }\n    },\n\n    uri: {\n      // TODO\n      /* ... */\n    },\n\n    \"utc-offset\": {\n      toICAL: function(aValue) {\n        if (aValue.length < 7) {\n          // no seconds\n          // -0500\n          return aValue.substr(0, 3) +\n                 aValue.substr(4, 2);\n        } else {\n          // seconds\n          // -050000\n          return aValue.substr(0, 3) +\n                 aValue.substr(4, 2) +\n                 aValue.substr(7, 2);\n        }\n      },\n\n      fromICAL: function(aValue) {\n        if (aValue.length < 6) {\n          // no seconds\n          // -05:00\n          return aValue.substr(0, 3) + ':' +\n                 aValue.substr(3, 2);\n        } else {\n          // seconds\n          // -05:00:00\n          return aValue.substr(0, 3) + ':' +\n                 aValue.substr(3, 2) + ':' +\n                 aValue.substr(5, 2);\n        }\n      },\n\n      decorate: function(aValue) {\n        return ICAL.UtcOffset.fromString(aValue);\n      },\n\n      undecorate: function(aValue) {\n        return aValue.toString();\n      }\n    }\n  };\n\n  var icalParams = {\n    // Although the syntax is DQUOTE uri DQUOTE, I don't think we should\n    // enfoce anything aside from it being a valid content line.\n    // \"ALTREP\": { ... },\n\n    // CN just wants a param-value\n    // \"CN\": { ... }\n\n    \"cutype\": {\n      values: [\"INDIVIDUAL\", \"GROUP\", \"RESOURCE\", \"ROOM\", \"UNKNOWN\"],\n      allowXName: true,\n      allowIanaToken: true\n    },\n\n    \"delegated-from\": {\n      valueType: \"cal-address\",\n      multiValue: \",\"\n    },\n    \"delegated-to\": {\n      valueType: \"cal-address\",\n      multiValue: \",\"\n    },\n    // \"DIR\": { ... }, // See ALTREP\n    \"encoding\": {\n      values: [\"8BIT\", \"BASE64\"]\n    },\n    // \"FMTTYPE\": { ... }, // See ALTREP\n    \"fbtype\": {\n      values: [\"FREE\", \"BUSY\", \"BUSY-UNAVAILABLE\", \"BUSY-TENTATIVE\"],\n      allowXName: true,\n      allowIanaToken: true\n    },\n    // \"LANGUAGE\": { ... }, // See ALTREP\n    \"member\": {\n      valueType: \"cal-address\",\n      multiValue: \",\"\n    },\n    \"partstat\": {\n      // TODO These values are actually different per-component\n      values: [\"NEEDS-ACTION\", \"ACCEPTED\", \"DECLINED\", \"TENTATIVE\",\n               \"DELEGATED\", \"COMPLETED\", \"IN-PROCESS\"],\n      allowXName: true,\n      allowIanaToken: true\n    },\n    \"range\": {\n      values: [\"THISLANDFUTURE\"]\n    },\n    \"related\": {\n      values: [\"START\", \"END\"]\n    },\n    \"reltype\": {\n      values: [\"PARENT\", \"CHILD\", \"SIBLING\"],\n      allowXName: true,\n      allowIanaToken: true\n    },\n    \"role\": {\n      values: [\"REQ-PARTICIPANT\", \"CHAIR\",\n               \"OPT-PARTICIPANT\", \"NON-PARTICIPANT\"],\n      allowXName: true,\n      allowIanaToken: true\n    },\n    \"rsvp\": {\n      values: [\"TRUE\", \"FALSE\"]\n    },\n    \"sent-by\": {\n      valueType: \"cal-address\"\n    },\n    \"tzid\": {\n      matches: /^\\//\n    },\n    \"value\": {\n      // since the value here is a 'type' lowercase is used.\n      values: [\"binary\", \"boolean\", \"cal-address\", \"date\", \"date-time\",\n               \"duration\", \"float\", \"integer\", \"period\", \"recur\", \"text\",\n               \"time\", \"uri\", \"utc-offset\"],\n      allowXName: true,\n      allowIanaToken: true\n    }\n  };\n\n  // When adding a value here, be sure to add it to the parameter types!\n  var icalValues = {\n    __proto__: commonValues,\n\n    \"binary\": {\n      decorate: function(aString) {\n        return ICAL.Binary.fromString(aString);\n      },\n\n      undecorate: function(aBinary) {\n        return aBinary.toString();\n      }\n    },\n    \"cal-address\": {\n      // needs to be an uri\n    },\n    \"date\": {\n      decorate: function(aValue, aProp) {\n        return ICAL.Time.fromDateString(aValue, aProp);\n      },\n\n      /**\n       * undecorates a time object.\n       */\n      undecorate: function(aValue) {\n        return aValue.toString();\n      },\n\n      fromICAL: function(aValue) {\n        // from: 20120901\n        // to: 2012-09-01\n        var result = aValue.substr(0, 4) + '-' +\n                     aValue.substr(4, 2) + '-' +\n                     aValue.substr(6, 2);\n\n        if (aValue[8] === 'Z') {\n          result += 'Z';\n        }\n\n        return result;\n      },\n\n      toICAL: function(aValue) {\n        // from: 2012-09-01\n        // to: 20120901\n\n        if (aValue.length > 11) {\n          //TODO: serialize warning?\n          return aValue;\n        }\n\n        var result = aValue.substr(0, 4) +\n                     aValue.substr(5, 2) +\n                     aValue.substr(8, 2);\n\n        if (aValue[10] === 'Z') {\n          result += 'Z';\n        }\n\n        return result;\n      }\n    },\n    \"date-time\": {\n      fromICAL: function(aValue) {\n        // from: 20120901T130000\n        // to: 2012-09-01T13:00:00\n        var result = aValue.substr(0, 4) + '-' +\n                     aValue.substr(4, 2) + '-' +\n                     aValue.substr(6, 2) + 'T' +\n                     aValue.substr(9, 2) + ':' +\n                     aValue.substr(11, 2) + ':' +\n                     aValue.substr(13, 2);\n\n        if (aValue[15] === 'Z') {\n          result += 'Z';\n        }\n\n        return result;\n      },\n\n      toICAL: function(aValue) {\n        // from: 2012-09-01T13:00:00\n        // to: 20120901T130000\n\n        if (aValue.length < 19) {\n          // TODO: error\n          return aValue;\n        }\n\n        var result = aValue.substr(0, 4) +\n                     aValue.substr(5, 2) +\n                     // grab the (DDTHH) segment\n                     aValue.substr(8, 5) +\n                     // MM\n                     aValue.substr(14, 2) +\n                     // SS\n                     aValue.substr(17, 2);\n\n        if (aValue[19] === 'Z') {\n          result += 'Z';\n        }\n\n        return result;\n      },\n\n      decorate: function(aValue, aProp) {\n        return ICAL.Time.fromDateTimeString(aValue, aProp);\n      },\n\n      undecorate: function(aValue) {\n        return aValue.toString();\n      }\n    },\n    duration: {\n      decorate: function(aValue) {\n        return ICAL.Duration.fromString(aValue);\n      },\n      undecorate: function(aValue) {\n        return aValue.toString();\n      }\n    },\n    period: {\n\n      fromICAL: function(string) {\n        var parts = string.split('/');\n        parts[0] = icalValues['date-time'].fromICAL(parts[0]);\n\n        if (!ICAL.Duration.isValueString(parts[1])) {\n          parts[1] = icalValues['date-time'].fromICAL(parts[1]);\n        }\n\n        return parts;\n      },\n\n      toICAL: function(parts) {\n        parts[0] = icalValues['date-time'].toICAL(parts[0]);\n\n        if (!ICAL.Duration.isValueString(parts[1])) {\n          parts[1] = icalValues['date-time'].toICAL(parts[1]);\n        }\n\n        return parts.join(\"/\");\n      },\n\n      decorate: function(aValue, aProp) {\n        return ICAL.Period.fromJSON(aValue, aProp);\n      },\n\n      undecorate: function(aValue) {\n        return aValue.toJSON();\n      }\n    },\n    recur: {\n      fromICAL: function(string) {\n        return ICAL.Recur._stringToData(string, true);\n      },\n\n      toICAL: function(data) {\n        var str = \"\";\n        for (var k in data) {\n          var val = data[k];\n          if (k == \"until\") {\n            if (val.length > 10) {\n              val = icalValues['date-time'].toICAL(val);\n            } else {\n              val = icalValues.date.toICAL(val);\n            }\n          } else if (k == \"wkst\") {\n            val = ICAL.Recur.numericDayToIcalDay(val);\n          } else if (Array.isArray(val)) {\n            val = val.join(\",\");\n          }\n          str += k.toUpperCase() + \"=\" + val + \";\";\n        }\n        return str.substr(0, str.length - 1);\n      },\n\n      decorate: function decorate(aValue) {\n        return ICAL.Recur.fromData(aValue);\n      },\n\n      undecorate: function(aRecur) {\n        return aRecur.toJSON();\n      }\n    },\n\n    time: {\n      fromICAL: function(aValue) {\n        // from: MMHHSS(Z)?\n        // to: HH:MM:SS(Z)?\n        if (aValue.length < 6) {\n          // TODO: parser exception?\n          return aValue;\n        }\n\n        // HH::MM::SSZ?\n        var result = aValue.substr(0, 2) + ':' +\n                     aValue.substr(2, 2) + ':' +\n                     aValue.substr(4, 2);\n\n        if (aValue[6] === 'Z') {\n          result += 'Z';\n        }\n\n        return result;\n      },\n\n      toICAL: function(aValue) {\n        // from: HH:MM:SS(Z)?\n        // to: MMHHSS(Z)?\n        if (aValue.length < 8) {\n          //TODO: error\n          return aValue;\n        }\n\n        var result = aValue.substr(0, 2) +\n                     aValue.substr(3, 2) +\n                     aValue.substr(6, 2);\n\n        if (aValue[8] === 'Z') {\n          result += 'Z';\n        }\n\n        return result;\n      }\n    }\n  };\n\n  var icalProperties = {\n    __proto__: commonProperties,\n\n    \"action\": DEFAULT_TYPE_TEXT,\n    \"attach\": { defaultType: \"uri\" },\n    \"attendee\": { defaultType: \"cal-address\" },\n    \"calscale\": DEFAULT_TYPE_TEXT,\n    \"class\": DEFAULT_TYPE_TEXT,\n    \"comment\": DEFAULT_TYPE_TEXT,\n    \"completed\": DEFAULT_TYPE_DATETIME,\n    \"contact\": DEFAULT_TYPE_TEXT,\n    \"created\": DEFAULT_TYPE_DATETIME,\n    \"description\": DEFAULT_TYPE_TEXT,\n    \"dtend\": DEFAULT_TYPE_DATETIME_DATE,\n    \"dtstamp\": DEFAULT_TYPE_DATETIME,\n    \"dtstart\": DEFAULT_TYPE_DATETIME_DATE,\n    \"due\": DEFAULT_TYPE_DATETIME_DATE,\n    \"duration\": { defaultType: \"duration\" },\n    \"exdate\": {\n      defaultType: \"date-time\",\n      allowedTypes: [\"date-time\", \"date\"],\n      multiValue: ','\n    },\n    \"exrule\": DEFAULT_TYPE_RECUR,\n    \"freebusy\": { defaultType: \"period\", multiValue: \",\" },\n    \"geo\": { defaultType: \"float\", structuredValue: \";\" },\n    \"last-modified\": DEFAULT_TYPE_DATETIME,\n    \"location\": DEFAULT_TYPE_TEXT,\n    \"method\": DEFAULT_TYPE_TEXT,\n    \"organizer\": { defaultType: \"cal-address\" },\n    \"percent-complete\": DEFAULT_TYPE_INTEGER,\n    \"priority\": DEFAULT_TYPE_INTEGER,\n    \"prodid\": DEFAULT_TYPE_TEXT,\n    \"related-to\": DEFAULT_TYPE_TEXT,\n    \"repeat\": DEFAULT_TYPE_INTEGER,\n    \"rdate\": {\n      defaultType: \"date-time\",\n      allowedTypes: [\"date-time\", \"date\", \"period\"],\n      multiValue: ',',\n      detectType: function(string) {\n        if (string.indexOf('/') !== -1) {\n          return 'period';\n        }\n        return (string.indexOf('T') === -1) ? 'date' : 'date-time';\n      }\n    },\n    \"recurrence-id\": DEFAULT_TYPE_DATETIME_DATE,\n    \"resources\": DEFAULT_TYPE_TEXT_MULTI,\n    \"request-status\": DEFAULT_TYPE_TEXT_STRUCTURED,\n    \"rrule\": DEFAULT_TYPE_RECUR,\n    \"sequence\": DEFAULT_TYPE_INTEGER,\n    \"status\": DEFAULT_TYPE_TEXT,\n    \"summary\": DEFAULT_TYPE_TEXT,\n    \"transp\": DEFAULT_TYPE_TEXT,\n    \"trigger\": { defaultType: \"duration\", allowedTypes: [\"duration\", \"date-time\"] },\n    \"tzoffsetfrom\": DEFAULT_TYPE_UTCOFFSET,\n    \"tzoffsetto\": DEFAULT_TYPE_UTCOFFSET,\n    \"tzurl\": DEFAULT_TYPE_URI,\n    \"tzid\": DEFAULT_TYPE_TEXT,\n    \"tzname\": DEFAULT_TYPE_TEXT\n  };\n\n  // When adding a value here, be sure to add it to the parameter types!\n  var vcardValues = {\n    __proto__: commonValues,\n\n    date: {\n      decorate: function(aValue) {\n        return ICAL.VCardTime.fromDateAndOrTimeString(aValue, \"date\");\n      },\n      undecorate: function(aValue) {\n        return aValue.toString();\n      },\n      fromICAL: function(aValue) {\n        if (aValue.length == 8) {\n          return icalValues.date.fromICAL(aValue);\n        } else if (aValue[0] == '-' && aValue.length == 6) {\n          return aValue.substr(0, 4) + '-' + aValue.substr(4);\n        } else {\n          return aValue;\n        }\n      },\n      toICAL: function(aValue) {\n        if (aValue.length == 10) {\n          return icalValues.date.toICAL(aValue);\n        } else if (aValue[0] == '-' && aValue.length == 7) {\n          return aValue.substr(0, 4) + aValue.substr(5);\n        } else {\n          return aValue;\n        }\n      }\n    },\n\n    time: {\n      decorate: function(aValue) {\n        return ICAL.VCardTime.fromDateAndOrTimeString(\"T\" + aValue, \"time\");\n      },\n      undecorate: function(aValue) {\n        return aValue.toString();\n      },\n      fromICAL: function(aValue) {\n        var splitzone = vcardValues.time._splitZone(aValue, true);\n        var zone = splitzone[0], value = splitzone[1];\n\n        //console.log(\"SPLIT: \",splitzone);\n\n        if (value.length == 6) {\n          value = value.substr(0, 2) + ':' +\n                  value.substr(2, 2) + ':' +\n                  value.substr(4, 2);\n        } else if (value.length == 4 && value[0] != '-') {\n          value = value.substr(0, 2) + ':' + value.substr(2, 2);\n        } else if (value.length == 5) {\n          value = value.substr(0, 3) + ':' + value.substr(3, 2);\n        }\n\n        if (zone.length == 5 && (zone[0] == '-' || zone[0] == '+')) {\n          zone = zone.substr(0, 3) + ':' + zone.substr(3);\n        }\n\n        return value + zone;\n      },\n\n      toICAL: function(aValue) {\n        var splitzone = vcardValues.time._splitZone(aValue);\n        var zone = splitzone[0], value = splitzone[1];\n\n        if (value.length == 8) {\n          value = value.substr(0, 2) +\n                  value.substr(3, 2) +\n                  value.substr(6, 2);\n        } else if (value.length == 5 && value[0] != '-') {\n          value = value.substr(0, 2) + value.substr(3, 2);\n        } else if (value.length == 6) {\n          value = value.substr(0, 3) + value.substr(4, 2);\n        }\n\n        if (zone.length == 6 && (zone[0] == '-' || zone[0] == '+')) {\n          zone = zone.substr(0, 3) + zone.substr(4);\n        }\n\n        return value + zone;\n      },\n\n      _splitZone: function(aValue, isFromIcal) {\n        var lastChar = aValue.length - 1;\n        var signChar = aValue.length - (isFromIcal ? 5 : 6);\n        var sign = aValue[signChar];\n        var zone, value;\n\n        if (aValue[lastChar] == 'Z') {\n          zone = aValue[lastChar];\n          value = aValue.substr(0, lastChar);\n        } else if (aValue.length > 6 && (sign == '-' || sign == '+')) {\n          zone = aValue.substr(signChar);\n          value = aValue.substr(0, signChar);\n        } else {\n          zone = \"\";\n          value = aValue;\n        }\n\n        return [zone, value];\n      }\n    },\n\n    \"date-time\": {\n      decorate: function(aValue) {\n        return ICAL.VCardTime.fromDateAndOrTimeString(aValue, \"date-time\");\n      },\n\n      undecorate: function(aValue) {\n        return aValue.toString();\n      },\n\n      fromICAL: function(aValue) {\n        return vcardValues['date-and-or-time'].fromICAL(aValue);\n      },\n\n      toICAL: function(aValue) {\n        return vcardValues['date-and-or-time'].toICAL(aValue);\n      }\n    },\n\n    \"date-and-or-time\": {\n      decorate: function(aValue) {\n        return ICAL.VCardTime.fromDateAndOrTimeString(aValue, \"date-and-or-time\");\n      },\n\n      undecorate: function(aValue) {\n        return aValue.toString();\n      },\n\n      fromICAL: function(aValue) {\n        var parts = aValue.split('T');\n        return (parts[0] ? vcardValues.date.fromICAL(parts[0]) : '') +\n               (parts[1] ? 'T' + vcardValues.time.fromICAL(parts[1]) : '');\n      },\n\n      toICAL: function(aValue) {\n        var parts = aValue.split('T');\n        return vcardValues.date.toICAL(parts[0]) +\n               (parts[1] ? 'T' + vcardValues.time.toICAL(parts[1]) : '');\n\n      }\n    },\n    timestamp: icalValues['date-time'],\n    \"language-tag\": {\n      matches: /^[a-zA-Z0-9\\-]+$/ // Could go with a more strict regex here\n    }\n  };\n\n  var vcardParams = {\n    \"type\": {\n      valueType: \"text\",\n      multiValue: \",\"\n    },\n    \"value\": {\n      // since the value here is a 'type' lowercase is used.\n      values: [\"text\", \"uri\", \"date\", \"time\", \"date-time\", \"date-and-or-time\",\n               \"timestamp\", \"boolean\", \"integer\", \"float\", \"utc-offset\",\n               \"language-tag\"],\n      allowXName: true,\n      allowIanaToken: true\n    }\n  };\n\n  var vcardProperties = {\n    __proto__: commonProperties,\n\n    \"adr\": DEFAULT_TYPE_TEXT_STRUCTURED,\n    \"anniversary\": DEFAULT_TYPE_DATE_ANDOR_TIME,\n    \"bday\": DEFAULT_TYPE_DATE_ANDOR_TIME,\n    \"caladruri\": DEFAULT_TYPE_URI,\n    \"caluri\": DEFAULT_TYPE_URI,\n    \"clientpidmap\": DEFAULT_TYPE_TEXT_STRUCTURED,\n    \"email\": DEFAULT_TYPE_TEXT,\n    \"fburl\": DEFAULT_TYPE_URI,\n    \"fn\": DEFAULT_TYPE_TEXT,\n    \"gender\": DEFAULT_TYPE_TEXT_STRUCTURED,\n    \"geo\": DEFAULT_TYPE_URI,\n    \"impp\": DEFAULT_TYPE_URI,\n    \"key\": DEFAULT_TYPE_URI,\n    \"kind\": DEFAULT_TYPE_TEXT,\n    \"lang\": { defaultType: \"language-tag\" },\n    \"logo\": DEFAULT_TYPE_URI,\n    \"member\": DEFAULT_TYPE_URI,\n    \"n\": { defaultType: \"text\", structuredValue: \";\", multiValue: \",\" },\n    \"nickname\": DEFAULT_TYPE_TEXT_MULTI,\n    \"note\": DEFAULT_TYPE_TEXT,\n    \"org\": DEFAULT_TYPE_TEXT_STRUCTURED,\n    \"photo\": DEFAULT_TYPE_URI,\n    \"related\": DEFAULT_TYPE_URI,\n    \"rev\": { defaultType: \"timestamp\" },\n    \"role\": DEFAULT_TYPE_TEXT,\n    \"sound\": DEFAULT_TYPE_URI,\n    \"source\": DEFAULT_TYPE_URI,\n    \"tel\": { defaultType: \"uri\", allowedTypes: [\"uri\", \"text\"] },\n    \"title\": DEFAULT_TYPE_TEXT,\n    \"tz\": { defaultType: \"text\", allowedTypes: [\"text\", \"utc-offset\", \"uri\"] },\n    \"xml\": DEFAULT_TYPE_TEXT\n  };\n\n  var icalSet = {\n    value: icalValues,\n    param: icalParams,\n    property: icalProperties\n  };\n\n  var vcardSet = {\n    value: vcardValues,\n    param: vcardParams,\n    property: vcardProperties\n  };\n\n  var design = {\n    defaultSet: icalSet,\n    defaultType: 'unknown',\n\n    getDesignSet: function(componentName) {\n      var isInDesign = componentName && componentName in design.components;\n      return isInDesign ? design.components[componentName] : design.defaultSet;\n    },\n\n    components: {\n      vcard: vcardSet,\n      vevent: icalSet,\n      vtodo: icalSet,\n      vjournal: icalSet,\n      valarm: icalSet,\n      vtimezone: icalSet,\n      daylight: icalSet,\n      standard: icalSet\n    },\n\n    icalendar: icalSet,\n    vcard: vcardSet\n  };\n\n  return design;\n}());\nICAL.stringify = (function() {\n  'use strict';\n\n  var LINE_ENDING = '\\r\\n';\n  var DEFAULT_VALUE_TYPE = 'unknown';\n\n  var design = ICAL.design;\n  var helpers = ICAL.helpers;\n\n  /**\n   * Convert a full jCal Array into a ical document.\n   *\n   * @param {Array} jCal document.\n   * @return {String} ical document.\n   */\n  function stringify(jCal) {\n    if (typeof jCal[0] == \"string\") {\n      // This is a single component\n      jCal = [jCal];\n    }\n\n    var i = 0;\n    var len = jCal.length;\n    var result = '';\n\n    for (; i < len; i++) {\n      result += stringify.component(jCal[i]) + LINE_ENDING;\n    }\n\n    return result;\n  }\n\n  /**\n   * Converts an jCal component array into a ICAL string.\n   * Recursive will resolve sub-components.\n   *\n   * Exact component/property order is not saved all\n   * properties will come before subcomponents.\n   *\n   * @param {Array} component   jCal fragment of a component.\n   * @param {Object} designSet  The design data to use for this component.\n   */\n  stringify.component = function(component, designSet) {\n    var name = component[0].toUpperCase();\n    var result = 'BEGIN:' + name + LINE_ENDING;\n    designSet = designSet || design.getDesignSet(component[0]);\n\n    var props = component[1];\n    var propIdx = 0;\n    var propLen = props.length;\n\n    for (; propIdx < propLen; propIdx++) {\n      result += stringify.property(props[propIdx], designSet) + LINE_ENDING;\n    }\n\n    var comps = component[2];\n    var compIdx = 0;\n    var compLen = comps.length;\n\n    for (; compIdx < compLen; compIdx++) {\n      result += stringify.component(comps[compIdx], designSet) + LINE_ENDING;\n    }\n\n    result += 'END:' + name;\n    return result;\n  };\n\n  /**\n   * Converts a single property to a ICAL string.\n   *\n   * @param {Array} property    jCal property.\n   * @param {Object} designSet  The design data to use for this property.\n   */\n  stringify.property = function(property, designSet) {\n    var name = property[0].toUpperCase();\n    var jsName = property[0];\n    var params = property[1];\n\n    var line = name;\n\n    var paramName;\n    for (paramName in params) {\n      var value = params[paramName];\n\n      /* istanbul ignore else */\n      if (params.hasOwnProperty(paramName)) {\n        var multiValue = (paramName in designSet.param) && designSet.param[paramName].multiValue;\n        if (multiValue && Array.isArray(value)) {\n          value = value.map(stringify._rfc6868Unescape);\n          value = stringify.multiValue(value, multiValue, \"unknown\", null, designSet);\n        } else {\n          value = stringify._rfc6868Unescape(value);\n        }\n\n\n        line += ';' + paramName.toUpperCase();\n        line += '=' + stringify.propertyValue(value);\n      }\n    }\n\n    if (property.length === 3) {\n      // If there are no values, we must assume a blank value\n      return line + ':';\n    }\n\n    var valueType = property[2];\n\n    if (!designSet) {\n      designSet = design.defaultSet;\n    }\n\n    var propDetails;\n    var multiValue = false;\n    var structuredValue = false;\n    var isDefault = false;\n\n    if (jsName in designSet.property) {\n      propDetails = designSet.property[jsName];\n\n      if ('multiValue' in propDetails) {\n        multiValue = propDetails.multiValue;\n      }\n\n      if (('structuredValue' in propDetails) && Array.isArray(property[3])) {\n        structuredValue = propDetails.structuredValue;\n      }\n\n      if ('defaultType' in propDetails) {\n        if (valueType === propDetails.defaultType) {\n          isDefault = true;\n        }\n      } else {\n        if (valueType === DEFAULT_VALUE_TYPE) {\n          isDefault = true;\n        }\n      }\n    } else {\n      if (valueType === DEFAULT_VALUE_TYPE) {\n        isDefault = true;\n      }\n    }\n\n    // push the VALUE property if type is not the default\n    // for the current property.\n    if (!isDefault) {\n      // value will never contain ;/:/, so we don't escape it here.\n      line += ';VALUE=' + valueType.toUpperCase();\n    }\n\n    line += ':';\n\n    if (multiValue && structuredValue) {\n      line += stringify.multiValue(\n        property[3], structuredValue, valueType, multiValue, designSet\n      );\n    } else if (multiValue) {\n      line += stringify.multiValue(\n        property.slice(3), multiValue, valueType, null, designSet\n      );\n    } else if (structuredValue) {\n      line += stringify.multiValue(\n        property[3], structuredValue, valueType, null, designSet\n      );\n    } else {\n      line += stringify.value(property[3], valueType, designSet);\n    }\n\n    return ICAL.helpers.foldline(line);\n  };\n\n  /**\n   * Handles escaping of property values that may contain:\n   *\n   *    COLON (:), SEMICOLON (;), or COMMA (,)\n   *\n   * If any of the above are present the result is wrapped\n   * in double quotes.\n   *\n   * @param {String} value raw value.\n   * @return {String} given or escaped value when needed.\n   */\n  stringify.propertyValue = function(value) {\n\n    if ((helpers.unescapedIndexOf(value, ',') === -1) &&\n        (helpers.unescapedIndexOf(value, ':') === -1) &&\n        (helpers.unescapedIndexOf(value, ';') === -1)) {\n\n      return value;\n    }\n\n    return '\"' + value + '\"';\n  };\n\n  /**\n   * Converts an array of ical values into a single\n   * string based on a type and a delimiter value (like \",\").\n   *\n   * @param {Array} values      list of values to convert.\n   * @param {String} delim      used to join the values usually (\",\", \";\", \":\").\n   * @param {String} type       lowecase ical value type\n   *                              (like boolean, date-time, etc..).\n   * @param {Object} designSet  The design data to use for this property.\n   *\n   * @return {String} ical string for value.\n   */\n  stringify.multiValue = function(values, delim, type, innerMulti, designSet) {\n    var result = '';\n    var len = values.length;\n    var i = 0;\n\n    for (; i < len; i++) {\n      if (innerMulti && Array.isArray(values[i])) {\n        result += stringify.multiValue(values[i], innerMulti, type, null, designSet);\n      } else {\n        result += stringify.value(values[i], type, designSet);\n      }\n\n      if (i !== (len - 1)) {\n        result += delim;\n      }\n    }\n\n    return result;\n  };\n\n  /**\n   * Processes a single ical value runs the associated \"toICAL\"\n   * method from the design value type if available to convert\n   * the value.\n   *\n   * @param {String|Numeric} value some formatted value.\n   * @param {String} type lowecase ical value type\n   *  (like boolean, date-time, etc..).\n   * @return {String} ical value for single value.\n   */\n  stringify.value = function(value, type, designSet) {\n    if (type in designSet.value && 'toICAL' in designSet.value[type]) {\n      return designSet.value[type].toICAL(value);\n    }\n    return value;\n  };\n\n  /**\n   * Internal helper for rfc6868. Exposing this on ICAL.stringify so that\n   * hackers can disable the rfc6868 parsing if the really need to.\n   */\n  stringify._rfc6868Unescape = function(val) {\n    return val.replace(/[\\n^\"]/g, function(x) {\n      return RFC6868_REPLACE_MAP[x];\n    });\n  };\n  var RFC6868_REPLACE_MAP = { '\"': \"^'\", \"\\n\": \"^n\", \"^\": \"^^\" };\n\n  return stringify;\n\n}());\n\nICAL.parse = (function() {\n  'use strict';\n\n  var CHAR = /[^ \\t]/;\n  var MULTIVALUE_DELIMITER = ',';\n  var VALUE_DELIMITER = ':';\n  var PARAM_DELIMITER = ';';\n  var PARAM_NAME_DELIMITER = '=';\n  var DEFAULT_VALUE_TYPE = 'unknown';\n  var DEFAULT_PARAM_TYPE = 'text';\n\n  var design = ICAL.design;\n  var helpers = ICAL.helpers;\n\n  function ParserError(message) {\n    this.message = message;\n\n    try {\n      throw new Error();\n    } catch (e) {\n      var split = e.stack.split('\\n');\n      split.shift();\n      this.stack = split.join('\\n');\n    }\n  }\n\n  ParserError.prototype = {\n    __proto__: Error.prototype\n  };\n\n  function parser(input) {\n    var state = {};\n    var root = state.component = [];\n\n    state.stack = [root];\n\n    parser._eachLine(input, function(err, line) {\n      parser._handleContentLine(line, state);\n    });\n\n\n    // when there are still items on the stack\n    // throw a fatal error, a component was not closed\n    // correctly in that case.\n    if (state.stack.length > 1) {\n      throw new ParserError(\n        'invalid ical body. component began but did not end'\n      );\n    }\n\n    state = null;\n\n    return (root.length == 1 ? root[0] : root);\n  }\n\n\n  /**\n   * Parse an iCalendar property value into the jCal for a single property\n   *\n   * @param {String} str        The iCalendar property string to parse.\n   * @param {Object} designSet  (optional) The design data to use for this property.\n   * @return {Object}           The jCal Object containing the property.\n   */\n  parser.property = function(str, designSet) {\n    var state = {\n      component: [[], []],\n      designSet: designSet || design.defaultSet\n    };\n    parser._handleContentLine(str, state);\n    return state.component[1][0];\n  };\n\n  /**\n   * Convenience method to parse a component. You can use ICAL.parse() directly\n   * instead.\n   *\n   * @param {String} str    The iCalendar component string to parse.\n   * @return {Object}       The jCal Object containing the component.\n   */\n  parser.component = function(str) {\n    return parser(str);\n  };\n\n  // classes & constants\n  parser.ParserError = ParserError;\n\n  parser._handleContentLine = function(line, state) {\n    // break up the parts of the line\n    var valuePos = line.indexOf(VALUE_DELIMITER);\n    var paramPos = line.indexOf(PARAM_DELIMITER);\n\n    var lastParamIndex;\n    var lastValuePos;\n\n    // name of property or begin/end\n    var name;\n    var value;\n    // params is only overridden if paramPos !== -1.\n    // we can't do params = params || {} later on\n    // because it sacrifices ops.\n    var params = {};\n\n    /**\n     * Different property cases\n     *\n     *\n     * 1. RRULE:FREQ=foo\n     *    // FREQ= is not a param but the value\n     *\n     * 2. ATTENDEE;ROLE=REQ-PARTICIPANT;\n     *    // ROLE= is a param because : has not happened yet\n     */\n      // when the parameter delimiter is after the\n      // value delimiter then its not a parameter.\n\n    if ((paramPos !== -1 && valuePos !== -1)) {\n      // when the parameter delimiter is after the\n      // value delimiter then its not a parameter.\n      if (paramPos > valuePos) {\n        paramPos = -1;\n      }\n    }\n\n    var parsedParams;\n    if (paramPos !== -1) {\n      name = line.substring(0, paramPos).toLowerCase();\n      parsedParams = parser._parseParameters(line.substring(paramPos), 0, state.designSet);\n      if (parsedParams[2] == -1) {\n        throw new ParserError(\"Invalid parameters in '\" + line + \"'\");\n      }\n      params = parsedParams[0];\n      lastParamIndex = parsedParams[1].length + parsedParams[2] + paramPos;\n      if ((lastValuePos =\n        line.substring(lastParamIndex).indexOf(VALUE_DELIMITER)) !== -1) {\n        value = line.substring(lastParamIndex + lastValuePos + 1);\n      } else {\n        throw new ParserError(\"Missing parameter value in '\" + line + \"'\");\n      }\n    } else if (valuePos !== -1) {\n      // without parmeters (BEGIN:VCAENDAR, CLASS:PUBLIC)\n      name = line.substring(0, valuePos).toLowerCase();\n      value = line.substring(valuePos + 1);\n\n      if (name === 'begin') {\n        var newComponent = [value.toLowerCase(), [], []];\n        if (state.stack.length === 1) {\n          state.component.push(newComponent);\n        } else {\n          state.component[2].push(newComponent);\n        }\n        state.stack.push(state.component);\n        state.component = newComponent;\n        if (!state.designSet) {\n          state.designSet = design.getDesignSet(state.component[0]);\n        }\n        return;\n      } else if (name === 'end') {\n        state.component = state.stack.pop();\n        return;\n      }\n      // If its not begin/end, then this is a property with an empty value,\n      // which should be considered valid.\n    } else {\n      /**\n       * Invalid line.\n       * The rational to throw an error is we will\n       * never be certain that the rest of the file\n       * is sane and its unlikely that we can serialize\n       * the result correctly either.\n       */\n      throw new ParserError(\n        'invalid line (no token \";\" or \":\") \"' + line + '\"'\n      );\n    }\n\n    var valueType;\n    var multiValue = false;\n    var structuredValue = false;\n    var propertyDetails;\n\n    if (name in state.designSet.property) {\n      propertyDetails = state.designSet.property[name];\n\n      if ('multiValue' in propertyDetails) {\n        multiValue = propertyDetails.multiValue;\n      }\n\n      if ('structuredValue' in propertyDetails) {\n        structuredValue = propertyDetails.structuredValue;\n      }\n\n      if (value && 'detectType' in propertyDetails) {\n        valueType = propertyDetails.detectType(value);\n      }\n    }\n\n    // attempt to determine value\n    if (!valueType) {\n      if (!('value' in params)) {\n        if (propertyDetails) {\n          valueType = propertyDetails.defaultType;\n        } else {\n          valueType = DEFAULT_VALUE_TYPE;\n        }\n      } else {\n        // possible to avoid this?\n        valueType = params.value.toLowerCase();\n      }\n    }\n\n    delete params.value;\n\n    /**\n     * Note on `var result` juggling:\n     *\n     * I observed that building the array in pieces has adverse\n     * effects on performance, so where possible we inline the creation.\n     * Its a little ugly but resulted in ~2000 additional ops/sec.\n     */\n\n    var result;\n    if (multiValue && structuredValue) {\n      value = parser._parseMultiValue(value, structuredValue, valueType, [], multiValue, state.designSet);\n      result = [name, params, valueType, value];\n    } else if (multiValue) {\n      result = [name, params, valueType];\n      parser._parseMultiValue(value, multiValue, valueType, result, null, state.designSet);\n    } else if (structuredValue) {\n      value = parser._parseMultiValue(value, structuredValue, valueType, [], null, state.designSet);\n      result = [name, params, valueType, value];\n    } else {\n      value = parser._parseValue(value, valueType, state.designSet);\n      result = [name, params, valueType, value];\n    }\n\n    state.component[1].push(result);\n  };\n\n  /**\n   * Parse a value from the raw value into the jCard/jCal value.\n   *\n   * @param {String} value          Original value.\n   * @param {String} type           Type of value.\n   * @param {Object} designSet      The design data to use for this value.\n   * @return {Object} varies on type.\n   */\n  parser._parseValue = function(value, type, designSet) {\n    if (type in designSet.value && 'fromICAL' in designSet.value[type]) {\n      return designSet.value[type].fromICAL(value);\n    }\n    return value;\n  };\n\n  /**\n   * Parse parameters from a string to object.\n   *\n   * @param {String} line           A single unfolded line.\n   * @param {Numeric} start         Position to start looking for properties.\n   * @param {Object} designSet      The design data to use for this property.\n   * @return {Object} key/value pairs.\n   */\n  parser._parseParameters = function(line, start, designSet) {\n    var lastParam = start;\n    var pos = 0;\n    var delim = PARAM_NAME_DELIMITER;\n    var result = {};\n    var name, lcname;\n    var value, valuePos = -1;\n    var type, multiValue;\n\n    // find the next '=' sign\n    // use lastParam and pos to find name\n    // check if \" is used if so get value from \"->\"\n    // then increment pos to find next ;\n\n    while ((pos !== false) &&\n           (pos = helpers.unescapedIndexOf(line, delim, pos + 1)) !== -1) {\n\n      name = line.substr(lastParam + 1, pos - lastParam - 1);\n      if (name.length == 0) {\n        throw new ParserError(\"Empty parameter name in '\" + line + \"'\");\n      }\n      lcname = name.toLowerCase();\n\n      var nextChar = line[pos + 1];\n      if (nextChar === '\"') {\n        valuePos = pos + 2;\n        pos = helpers.unescapedIndexOf(line, '\"', valuePos);\n        if (pos === -1) {\n          throw new ParserError(\n            'invalid line (no matching double quote) \"' + line + '\"'\n          );\n        }\n        value = line.substr(valuePos, pos - valuePos);\n        lastParam = helpers.unescapedIndexOf(line, PARAM_DELIMITER, pos);\n        if (lastParam === -1) {\n          pos = false;\n        }\n      } else {\n        valuePos = pos + 1;\n\n        // move to next \";\"\n        var nextPos = helpers.unescapedIndexOf(line, PARAM_DELIMITER, valuePos);\n        var propValuePos = helpers.unescapedIndexOf(line, VALUE_DELIMITER, valuePos);\n        if (propValuePos !== -1 && nextPos > propValuePos) {\n          // this is a delimiter in the property value, let's stop here\n          nextPos = propValuePos;\n          pos = false;\n        } else if (nextPos === -1) {\n          // no \";\"\n          if (propValuePos === -1) {\n            nextPos = line.length;\n          } else {\n            nextPos = propValuePos;\n          }\n          pos = false;\n        } else {\n          lastParam = nextPos;\n        }\n\n        value = line.substr(valuePos, nextPos - valuePos);\n      }\n\n      if (lcname in designSet.param && designSet.param[lcname].valueType) {\n        type = designSet.param[lcname].valueType;\n      } else {\n        type = DEFAULT_PARAM_TYPE;\n      }\n\n      if (lcname in designSet.param) {\n        multiValue = designSet.param[lcname].multiValue;\n      }\n\n      value = parser._rfc6868Escape(value);\n      if (multiValue) {\n        result[lcname] = parser._parseMultiValue(value, multiValue, type, [], null, designSet);\n      } else {\n        result[lcname] = parser._parseValue(value, type, designSet);\n      }\n    }\n    return [result, value, valuePos];\n  };\n\n  /**\n   * Internal helper for rfc6868. Exposing this on ICAL.parse so that\n   * hackers can disable the rfc6868 parsing if the really need to.\n   */\n  parser._rfc6868Escape = function(val) {\n    return val.replace(/\\^['n^]/g, function(x) {\n      return RFC6868_REPLACE_MAP[x];\n    });\n  };\n  var RFC6868_REPLACE_MAP = { \"^'\": '\"', \"^n\": \"\\n\", \"^^\": \"^\" };\n\n  /**\n   * Parse a multi value string\n   */\n  parser._parseMultiValue = function(buffer, delim, type, result, innerMulti, designSet) {\n    var pos = 0;\n    var lastPos = 0;\n    var value;\n\n    // split each piece\n    while ((pos = helpers.unescapedIndexOf(buffer, delim, lastPos)) !== -1) {\n      value = buffer.substr(lastPos, pos - lastPos);\n      if (innerMulti) {\n        value = parser._parseMultiValue(value, innerMulti, type, [], null, designSet);\n      } else {\n        value = parser._parseValue(value, type, designSet);\n      }\n      result.push(value);\n      lastPos = pos + 1;\n    }\n\n    // on the last piece take the rest of string\n    value = buffer.substr(lastPos);\n    if (innerMulti) {\n      value = parser._parseMultiValue(value, innerMulti, type, [], null, designSet);\n    } else {\n      value = parser._parseValue(value, type, designSet);\n    }\n    result.push(value);\n\n    return result.length == 1 ? result[0] : result;\n  };\n\n  parser._eachLine = function(buffer, callback) {\n    var len = buffer.length;\n    var lastPos = buffer.search(CHAR);\n    var pos = lastPos;\n    var line;\n    var firstChar;\n\n    var newlineOffset;\n\n    do {\n      pos = buffer.indexOf('\\n', lastPos) + 1;\n\n      if (buffer[pos - 2] === '\\r') {\n        newlineOffset = 2;\n      } else {\n        newlineOffset = 1;\n      }\n\n      if (pos === 0) {\n        pos = len;\n        newlineOffset = 0;\n      }\n\n      firstChar = buffer[lastPos];\n\n      if (firstChar === ' ' || firstChar === '\\t') {\n        // add to line\n        line += buffer.substr(\n          lastPos + 1,\n          pos - lastPos - (newlineOffset + 1)\n        );\n      } else {\n        if (line)\n          callback(null, line);\n        // push line\n        line = buffer.substr(\n          lastPos,\n          pos - lastPos - newlineOffset\n        );\n      }\n\n      lastPos = pos;\n    } while (pos !== len);\n\n    // extra ending line\n    line = line.trim();\n\n    if (line.length)\n      callback(null, line);\n  };\n\n  return parser;\n\n}());\nICAL.Component = (function() {\n  'use strict';\n\n  var PROPERTY_INDEX = 1;\n  var COMPONENT_INDEX = 2;\n  var NAME_INDEX = 0;\n\n  /**\n   * Create a wrapper for a jCal component.\n   *\n   * @param {Array|String} jCal\n   *  raw jCal component data OR name of new component.\n   * @param {ICAL.Component} parent parent component to associate.\n   */\n  function Component(jCal, parent) {\n    if (typeof(jCal) === 'string') {\n      // jCal spec (name, properties, components)\n      jCal = [jCal, [], []];\n    }\n\n    // mostly for legacy reasons.\n    this.jCal = jCal;\n\n    this.parent = parent || null;\n  }\n\n  Component.prototype = {\n    /**\n     * Hydrated properties are inserted into the _properties array at the same\n     * position as in the jCal array, so its possible the array contains\n     * undefined values for unhydrdated properties. To avoid iterating the\n     * array when checking if all properties have been hydrated, we save the\n     * count here.\n     */\n    _hydratedPropertyCount: 0,\n\n    /**\n     * The same count as for _hydratedPropertyCount, but for subcomponents\n     */\n    _hydratedComponentCount: 0,\n\n    get name() {\n      return this.jCal[NAME_INDEX];\n    },\n\n    get _designSet() {\n      var parentDesign = this.parent && this.parent._designSet;\n      return parentDesign || ICAL.design.getDesignSet(this.name);\n    },\n\n    _hydrateComponent: function(index) {\n      if (!this._components) {\n        this._components = [];\n        this._hydratedComponentCount = 0;\n      }\n\n      if (this._components[index]) {\n        return this._components[index];\n      }\n\n      var comp = new Component(\n        this.jCal[COMPONENT_INDEX][index],\n        this\n      );\n\n      this._hydratedComponentCount++;\n      return (this._components[index] = comp);\n    },\n\n    _hydrateProperty: function(index) {\n      if (!this._properties) {\n        this._properties = [];\n        this._hydratedPropertyCount = 0;\n      }\n\n      if (this._properties[index]) {\n        return this._properties[index];\n      }\n\n      var prop = new ICAL.Property(\n        this.jCal[PROPERTY_INDEX][index],\n        this\n      );\n\n      this._hydratedPropertyCount++;\n      return (this._properties[index] = prop);\n    },\n\n    /**\n     * Finds first sub component, optionally filtered by name.\n     *\n     * @param {String} [name] optional name to filter by.\n     */\n    getFirstSubcomponent: function(name) {\n      if (name) {\n        var i = 0;\n        var comps = this.jCal[COMPONENT_INDEX];\n        var len = comps.length;\n\n        for (; i < len; i++) {\n          if (comps[i][NAME_INDEX] === name) {\n            var result = this._hydrateComponent(i);\n            return result;\n          }\n        }\n      } else {\n        if (this.jCal[COMPONENT_INDEX].length) {\n          return this._hydrateComponent(0);\n        }\n      }\n\n      // ensure we return a value (strict mode)\n      return null;\n    },\n\n    /**\n     * Finds all sub components, optionally filtering by name.\n     *\n     * @param {String} [name] optional name to filter by.\n     */\n    getAllSubcomponents: function(name) {\n      var jCalLen = this.jCal[COMPONENT_INDEX].length;\n      var i = 0;\n\n      if (name) {\n        var comps = this.jCal[COMPONENT_INDEX];\n        var result = [];\n\n        for (; i < jCalLen; i++) {\n          if (name === comps[i][NAME_INDEX]) {\n            result.push(\n              this._hydrateComponent(i)\n            );\n          }\n        }\n        return result;\n      } else {\n        if (!this._components ||\n            (this._hydratedComponentCount !== jCalLen)) {\n          for (; i < jCalLen; i++) {\n            this._hydrateComponent(i);\n          }\n        }\n\n        return this._components || [];\n      }\n    },\n\n    /**\n     * Returns true when a named property exists.\n     *\n     * @param {String} name property name.\n     * @return {Boolean} true when property is found.\n     */\n    hasProperty: function(name) {\n      var props = this.jCal[PROPERTY_INDEX];\n      var len = props.length;\n\n      var i = 0;\n      for (; i < len; i++) {\n        // 0 is property name\n        if (props[i][NAME_INDEX] === name) {\n          return true;\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * Finds first property.\n     *\n     * @param {String} [name] lowercase name of property.\n     * @return {ICAL.Property} found property.\n     */\n    getFirstProperty: function(name) {\n      if (name) {\n        var i = 0;\n        var props = this.jCal[PROPERTY_INDEX];\n        var len = props.length;\n\n        for (; i < len; i++) {\n          if (props[i][NAME_INDEX] === name) {\n            var result = this._hydrateProperty(i);\n            return result;\n          }\n        }\n      } else {\n        if (this.jCal[PROPERTY_INDEX].length) {\n          return this._hydrateProperty(0);\n        }\n      }\n\n      return null;\n    },\n\n    /**\n     * Returns first properties value if available.\n     *\n     * @param {String} [name] (lowecase) property name.\n     * @return {String} property value.\n     */\n    getFirstPropertyValue: function(name) {\n      var prop = this.getFirstProperty(name);\n      if (prop) {\n        return prop.getFirstValue();\n      }\n\n      return null;\n    },\n\n    /**\n     * get all properties in the component.\n     *\n     * @param {String} [name] (lowercase) property name.\n     * @return {Array[ICAL.Property]} list of properties.\n     */\n    getAllProperties: function(name) {\n      var jCalLen = this.jCal[PROPERTY_INDEX].length;\n      var i = 0;\n\n      if (name) {\n        var props = this.jCal[PROPERTY_INDEX];\n        var result = [];\n\n        for (; i < jCalLen; i++) {\n          if (name === props[i][NAME_INDEX]) {\n            result.push(\n              this._hydrateProperty(i)\n            );\n          }\n        }\n        return result;\n      } else {\n        if (!this._properties ||\n            (this._hydratedPropertyCount !== jCalLen)) {\n          for (; i < jCalLen; i++) {\n            this._hydrateProperty(i);\n          }\n        }\n\n        return this._properties || [];\n      }\n    },\n\n    _removeObjectByIndex: function(jCalIndex, cache, index) {\n      // remove cached version\n      if (cache && cache[index]) {\n        var obj = cache[index];\n        if (\"parent\" in obj) {\n            obj.parent = null;\n        }\n        cache.splice(index, 1);\n      }\n\n      // remove it from the jCal\n      this.jCal[jCalIndex].splice(index, 1);\n    },\n\n    _removeObject: function(jCalIndex, cache, nameOrObject) {\n      var i = 0;\n      var objects = this.jCal[jCalIndex];\n      var len = objects.length;\n      var cached = this[cache];\n\n      if (typeof(nameOrObject) === 'string') {\n        for (; i < len; i++) {\n          if (objects[i][NAME_INDEX] === nameOrObject) {\n            this._removeObjectByIndex(jCalIndex, cached, i);\n            return true;\n          }\n        }\n      } else if (cached) {\n        for (; i < len; i++) {\n          if (cached[i] && cached[i] === nameOrObject) {\n            this._removeObjectByIndex(jCalIndex, cached, i);\n            return true;\n          }\n        }\n      }\n\n      return false;\n    },\n\n    _removeAllObjects: function(jCalIndex, cache, name) {\n      var cached = this[cache];\n\n      // Unfortunately we have to run through all children to reset their\n      // parent property.\n      var objects = this.jCal[jCalIndex];\n      var i = objects.length - 1;\n\n      // descending search required because splice\n      // is used and will effect the indices.\n      for (; i >= 0; i--) {\n        if (!name || objects[i][NAME_INDEX] === name) {\n          this._removeObjectByIndex(jCalIndex, cached, i);\n        }\n      }\n    },\n\n    /**\n     * Adds a single sub component.\n     *\n     * @param {ICAL.Component} component to add.\n     */\n    addSubcomponent: function(component) {\n      if (!this._components) {\n        this._components = [];\n        this._hydratedComponentCount = 0;\n      }\n\n      if (component.parent) {\n        component.parent.removeSubcomponent(component);\n      }\n\n      var idx = this.jCal[COMPONENT_INDEX].push(component.jCal);\n      this._components[idx - 1] = component;\n      this._hydratedComponentCount++;\n      component.parent = this;\n    },\n\n    /**\n     * Removes a single component by name or\n     * the instance of a specific component.\n     *\n     * @param {ICAL.Component|String} nameOrComp comp type.\n     * @return {Boolean} true when comp is removed.\n     */\n    removeSubcomponent: function(nameOrComp) {\n      var removed = this._removeObject(COMPONENT_INDEX, '_components', nameOrComp);\n      if (removed) {\n        this._hydratedComponentCount--;\n      }\n      return removed;\n    },\n\n    /**\n     * Removes all components or (if given) all\n     * components by a particular name.\n     *\n     * @param {String} [name] (lowercase) component name.\n     */\n    removeAllSubcomponents: function(name) {\n      var removed = this._removeAllObjects(COMPONENT_INDEX, '_components', name);\n      this._hydratedComponentCount = 0;\n      return removed;\n    },\n\n    /**\n     * Adds a property to the component.\n     *\n     * @param {ICAL.Property} property object.\n     */\n    addProperty: function(property) {\n      if (!(property instanceof ICAL.Property)) {\n        throw new TypeError('must instance of ICAL.Property');\n      }\n\n      if (!this._properties) {\n        this._properties = [];\n        this._hydratedPropertyCount = 0;\n      }\n\n\n      if (property.parent) {\n        property.parent.removeProperty(property);\n      }\n\n      var idx = this.jCal[PROPERTY_INDEX].push(property.jCal);\n      this._properties[idx - 1] = property;\n      this._hydratedPropertyCount++;\n      property.parent = this;\n    },\n\n    /**\n     * Helper method to add a property with a value to the component.\n     *\n     * @param {String} name property name to add.\n     * @param {Object} value property value.\n     */\n    addPropertyWithValue: function(name, value) {\n      var prop = new ICAL.Property(name);\n      prop.setValue(value);\n\n      this.addProperty(prop);\n\n      return prop;\n    },\n\n    /**\n     * Helper method that will update or create a property\n     * of the given name and sets its value.\n     *\n     * @param {String} name property name.\n     * @param {Object} value property value.\n     * @return {ICAL.Property} property.\n     */\n    updatePropertyWithValue: function(name, value) {\n      var prop = this.getFirstProperty(name);\n\n      if (prop) {\n        prop.setValue(value);\n      } else {\n        prop = this.addPropertyWithValue(name, value);\n      }\n\n      return prop;\n    },\n\n    /**\n     * Removes a single property by name or\n     * the instance of the specific property.\n     *\n     * @param {String|ICAL.Property} nameOrProp to remove.\n     * @return {Boolean} true when deleted.\n     */\n    removeProperty: function(nameOrProp) {\n      var removed = this._removeObject(PROPERTY_INDEX, '_properties', nameOrProp);\n      if (removed) {\n        this._hydratedPropertyCount--;\n      }\n      return removed;\n    },\n\n    /**\n     * Removes all properties associated with this component.\n     *\n     * @param {String} [name] (lowecase) optional property name.\n     */\n    removeAllProperties: function(name) {\n      var removed = this._removeAllObjects(PROPERTY_INDEX, '_properties', name);\n      this._hydratedPropertyCount = 0;\n      return removed;\n    },\n\n    toJSON: function() {\n      return this.jCal;\n    },\n\n    toString: function() {\n      return ICAL.stringify.component(\n        this.jCal, this._designSet\n      );\n    }\n  };\n\n  Component.fromString = function(str) {\n    return new Component(ICAL.parse.component(str));\n  };\n\n  return Component;\n\n}());\nICAL.Property = (function() {\n  'use strict';\n\n  var NAME_INDEX = 0;\n  var PROP_INDEX = 1;\n  var TYPE_INDEX = 2;\n  var VALUE_INDEX = 3;\n\n  var design = ICAL.design;\n\n  /**\n   * Provides a nicer interface to any kind of property.\n   * Its important to note that mutations done in the wrapper\n   * directly effect (mutate) the jCal object used to initialize.\n   *\n   * Can also be used to create new properties by passing\n   * the name of the property (as a String).\n   *\n   *\n   * @param {Array|String} jCal raw jCal representation OR\n   *  the new name of the property (when creating).\n   *\n   * @param {ICAL.Component} [parent] parent component.\n   */\n  function Property(jCal, parent) {\n    this._parent = parent || null;\n\n    if (typeof(jCal) === 'string') {\n      // We are creating the property by name and need to detect the type\n      this.jCal = [jCal, {}, design.defaultType];\n      this.jCal[TYPE_INDEX] = this.getDefaultType();\n    } else {\n      this.jCal = jCal;\n    }\n    this._updateType();\n  }\n\n  Property.prototype = {\n    get type() {\n      return this.jCal[TYPE_INDEX];\n    },\n\n    get name() {\n      return this.jCal[NAME_INDEX];\n    },\n\n    get parent() {\n      return this._parent;\n    },\n\n    set parent(p) {\n      this._parent = p;\n\n      // Changing the parent might change the design set, in that case we need\n      // to update the default type.\n      var designSetChanged = !this._parent || (p && p._designSet != this._parent._designSet);\n      if (this.type == design.defaultType && designSetChanged) {\n        this.jCal[TYPE_INDEX] = this.getDefaultType();\n        this._updateType();\n      }\n\n      return p;\n    },\n\n    get _designSet() {\n      return this.parent ? this.parent._designSet : design.defaultSet;\n    },\n\n    _updateType: function() {\n      var designSet = this._designSet;\n\n      if (this.type in designSet.value) {\n        var designType = designSet.value[this.type];\n\n        if ('decorate' in designSet.value[this.type]) {\n          this.isDecorated = true;\n        } else {\n          this.isDecorated = false;\n        }\n\n        if (this.name in designSet.property) {\n          this.isMultiValue = ('multiValue' in designSet.property[this.name]);\n          this.isStructuredValue = ('structuredValue' in designSet.property[this.name]);\n        }\n      }\n    },\n\n    /**\n     * Hydrate a single value.\n     */\n    _hydrateValue: function(index) {\n      if (this._values && this._values[index]) {\n        return this._values[index];\n      }\n\n      // for the case where there is no value.\n      if (this.jCal.length <= (VALUE_INDEX + index)) {\n        return null;\n      }\n\n      if (this.isDecorated) {\n        if (!this._values) {\n          this._values = [];\n        }\n        return (this._values[index] = this._decorate(\n          this.jCal[VALUE_INDEX + index]\n        ));\n      } else {\n        return this.jCal[VALUE_INDEX + index];\n      }\n    },\n\n    _decorate: function(value) {\n      return this._designSet.value[this.type].decorate(value, this);\n    },\n\n    _undecorate: function(value) {\n      return this._designSet.value[this.type].undecorate(value, this);\n    },\n\n    _setDecoratedValue: function(value, index) {\n      if (!this._values) {\n        this._values = [];\n      }\n\n      if (typeof(value) === 'object' && 'icaltype' in value) {\n        // decorated value\n        this.jCal[VALUE_INDEX + index] = this._undecorate(value);\n        this._values[index] = value;\n      } else {\n        // undecorated value\n        this.jCal[VALUE_INDEX + index] = value;\n        this._values[index] = this._decorate(value);\n      }\n    },\n\n    /**\n     * Gets a param on the property.\n     *\n     * @param {String} name prop name (lowercase).\n     * @return {String} prop value.\n     */\n    getParameter: function(name) {\n      return this.jCal[PROP_INDEX][name];\n    },\n\n    /**\n     * Sets a param on the property.\n     *\n     * @param {String} value property value.\n     */\n    setParameter: function(name, value) {\n      this.jCal[PROP_INDEX][name] = value;\n    },\n\n    /**\n     * Removes a parameter\n     *\n     * @param {String} name prop name (lowercase).\n     */\n    removeParameter: function(name) {\n      return delete this.jCal[PROP_INDEX][name];\n    },\n\n    /**\n     * Get the default type based on this property's name.\n     *\n     * @return {String} the default type for this property.\n     */\n    getDefaultType: function() {\n      var name = this.jCal[NAME_INDEX];\n      var designSet = this._designSet;\n\n      if (name in designSet.property) {\n        var details = designSet.property[name];\n        if ('defaultType' in details) {\n          return details.defaultType;\n        }\n      }\n      return design.defaultType;\n    },\n\n    /**\n     * Sets type of property and clears out any\n     * existing values of the current type.\n     *\n     * @param {String} type new iCAL type (see design.*.values).\n     */\n    resetType: function(type) {\n      this.removeAllValues();\n      this.jCal[TYPE_INDEX] = type;\n      this._updateType();\n    },\n\n    /**\n     * Finds first property value.\n     *\n     * @return {String} first property value.\n     */\n    getFirstValue: function() {\n      return this._hydrateValue(0);\n    },\n\n    /**\n     * Gets all values on the property.\n     *\n     * NOTE: this creates an array during each call.\n     *\n     * @return {Array} list of values.\n     */\n    getValues: function() {\n      var len = this.jCal.length - VALUE_INDEX;\n\n      if (len < 1) {\n        // its possible for a property to have no value.\n        return [];\n      }\n\n      var i = 0;\n      var result = [];\n\n      for (; i < len; i++) {\n        result[i] = this._hydrateValue(i);\n      }\n\n      return result;\n    },\n\n    removeAllValues: function() {\n      if (this._values) {\n        this._values.length = 0;\n      }\n      this.jCal.length = 3;\n    },\n\n    /**\n     * Sets the values of the property.\n     * Will overwrite the existing values.\n     *\n     * @param {Array} values an array of values.\n     */\n    setValues: function(values) {\n      if (!this.isMultiValue) {\n        throw new Error(\n          this.name + ': does not not support mulitValue.\\n' +\n          'override isMultiValue'\n        );\n      }\n\n      var len = values.length;\n      var i = 0;\n      this.removeAllValues();\n\n      if (len > 0 &&\n          typeof(values[0]) === 'object' &&\n          'icaltype' in values[0]) {\n        this.resetType(values[0].icaltype);\n      }\n\n      if (this.isDecorated) {\n        for (; i < len; i++) {\n          this._setDecoratedValue(values[i], i);\n        }\n      } else {\n        for (; i < len; i++) {\n          this.jCal[VALUE_INDEX + i] = values[i];\n        }\n      }\n    },\n\n    /**\n     * Sets the current value of the property. If this is a multi-value\n     * property, all other values will be removed.\n     *\n     * @param {String|Object} value new prop value.\n     */\n    setValue: function(value) {\n      this.removeAllValues();\n      if (typeof(value) === 'object' && 'icaltype' in value) {\n        this.resetType(value.icaltype);\n      }\n\n      if (this.isDecorated) {\n        this._setDecoratedValue(value, 0);\n      } else {\n        this.jCal[VALUE_INDEX] = value;\n      }\n    },\n\n    /**\n     * Returns the jCal representation of this property.\n     *\n     * @return {Object} jCal.\n     */\n    toJSON: function() {\n      return this.jCal;\n    },\n\n    toICAL: function() {\n      return ICAL.stringify.property(\n        this.jCal, this._designSet\n      );\n    }\n\n  };\n\n  Property.fromString = function(str) {\n    return new Property(ICAL.parse.property(str));\n  };\n\n  return Property;\n\n}());\nICAL.UtcOffset = (function() {\n\n  function UtcOffset(aData) {\n    if (aData) {\n      this.hours = aData.hours;\n      this.minutes = aData.minutes;\n      this.factor = aData.factor;\n    }\n  }\n\n  UtcOffset.prototype = {\n\n    hours: null,\n    minutes: null,\n    factor: null,\n\n    icaltype: \"utc-offset\",\n\n    toSeconds: function() {\n      return this.factor * (60 * this.minutes + 3600 * this.hours);\n    },\n\n    fromSeconds: function(aSeconds) {\n      var secs = Math.abs(aSeconds);\n\n      this.factor = aSeconds < 0 ? -1 : 1;\n      this.hours = ICAL.helpers.trunc(secs / 3600);\n\n      secs -= (this.hours * 3600);\n      this.minutes = ICAL.helpers.trunc(secs / 60);\n      return this;\n    },\n\n\n    toString: function toString() {\n      return (this.factor == 1 ? \"+\" : \"-\") +\n              ICAL.helpers.pad2(this.hours) + ':' +\n              ICAL.helpers.pad2(this.minutes);\n    }\n  };\n\n  UtcOffset.fromString = function(aString) {\n    // -05:00\n    var options = {};\n    //TODO: support seconds per rfc5545 ?\n    options.factor = (aString[0] === '+') ? 1 : -1;\n    options.hours = ICAL.helpers.strictParseInt(aString.substr(1, 2));\n    options.minutes = ICAL.helpers.strictParseInt(aString.substr(4, 2));\n\n    return new ICAL.UtcOffset(options);\n  };\n\n  UtcOffset.fromSeconds = function(aSeconds) {\n    var instance = new UtcOffset();\n    instance.fromSeconds(aSeconds);\n    return instance;\n  };\n\n  return UtcOffset;\n\n}());\nICAL.Binary = (function() {\n\n  function Binary(aValue) {\n    this.value = aValue;\n  }\n\n  Binary.prototype = {\n    icaltype: \"binary\",\n\n    decodeValue: function decodeValue() {\n      return this._b64_decode(this.value);\n    },\n\n    setEncodedValue: function setEncodedValue(val) {\n      this.value = this._b64_encode(val);\n    },\n\n    _b64_encode: function base64_encode(data) {\n      // http://kevin.vanzonneveld.net\n      // +   original by: Tyler Akins (http://rumkin.com)\n      // +   improved by: Bayron Guevara\n      // +   improved by: Thunder.m\n      // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n      // +   bugfixed by: Pellentesque Malesuada\n      // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n      // +   improved by: Rafał Kukawski (http://kukawski.pl)\n      // *     example 1: base64_encode('Kevin van Zonneveld');\n      // *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='\n      // mozilla has this native\n      // - but breaks in 2.0.0.12!\n      //if (typeof this.window['atob'] == 'function') {\n      //    return atob(data);\n      //}\n      var b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" +\n                \"abcdefghijklmnopqrstuvwxyz0123456789+/=\";\n      var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,\n        ac = 0,\n        enc = \"\",\n        tmp_arr = [];\n\n      if (!data) {\n        return data;\n      }\n\n      do { // pack three octets into four hexets\n        o1 = data.charCodeAt(i++);\n        o2 = data.charCodeAt(i++);\n        o3 = data.charCodeAt(i++);\n\n        bits = o1 << 16 | o2 << 8 | o3;\n\n        h1 = bits >> 18 & 0x3f;\n        h2 = bits >> 12 & 0x3f;\n        h3 = bits >> 6 & 0x3f;\n        h4 = bits & 0x3f;\n\n        // use hexets to index into b64, and append result to encoded string\n        tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);\n      } while (i < data.length);\n\n      enc = tmp_arr.join('');\n\n      var r = data.length % 3;\n\n      return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);\n\n    },\n\n    _b64_decode: function base64_decode(data) {\n      // http://kevin.vanzonneveld.net\n      // +   original by: Tyler Akins (http://rumkin.com)\n      // +   improved by: Thunder.m\n      // +      input by: Aman Gupta\n      // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n      // +   bugfixed by: Onno Marsman\n      // +   bugfixed by: Pellentesque Malesuada\n      // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n      // +      input by: Brett Zamir (http://brett-zamir.me)\n      // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\n      // *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');\n      // *     returns 1: 'Kevin van Zonneveld'\n      // mozilla has this native\n      // - but breaks in 2.0.0.12!\n      //if (typeof this.window['btoa'] == 'function') {\n      //    return btoa(data);\n      //}\n      var b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" +\n                \"abcdefghijklmnopqrstuvwxyz0123456789+/=\";\n      var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,\n        ac = 0,\n        dec = \"\",\n        tmp_arr = [];\n\n      if (!data) {\n        return data;\n      }\n\n      data += '';\n\n      do { // unpack four hexets into three octets using index points in b64\n        h1 = b64.indexOf(data.charAt(i++));\n        h2 = b64.indexOf(data.charAt(i++));\n        h3 = b64.indexOf(data.charAt(i++));\n        h4 = b64.indexOf(data.charAt(i++));\n\n        bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;\n\n        o1 = bits >> 16 & 0xff;\n        o2 = bits >> 8 & 0xff;\n        o3 = bits & 0xff;\n\n        if (h3 == 64) {\n          tmp_arr[ac++] = String.fromCharCode(o1);\n        } else if (h4 == 64) {\n          tmp_arr[ac++] = String.fromCharCode(o1, o2);\n        } else {\n          tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);\n        }\n      } while (i < data.length);\n\n      dec = tmp_arr.join('');\n\n      return dec;\n    },\n\n    toString: function() {\n      return this.value;\n    }\n  };\n\n  Binary.fromString = function(aString) {\n    return new Binary(aString);\n  };\n\n  return Binary;\n\n}());\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2011-2012 */\n\n\n\n/* istanbul ignore next */\n(typeof(ICAL) === 'undefined') ? ICAL = {} : ''; // jshint ignore:line\n\n(function() {\n  ICAL.Period = function icalperiod(aData) {\n    this.wrappedJSObject = this;\n\n    if (aData && 'start' in aData) {\n      if (aData.start && !(aData.start instanceof ICAL.Time)) {\n        throw new TypeError('.start must be an instance of ICAL.Time');\n      }\n      this.start = aData.start;\n    }\n\n    if (aData && aData.end && aData.duration) {\n      throw new Error('cannot accept both end and duration');\n    }\n\n    if (aData && 'end' in aData) {\n      if (aData.end && !(aData.end instanceof ICAL.Time)) {\n        throw new TypeError('.end must be an instance of ICAL.Time');\n      }\n      this.end = aData.end;\n    }\n\n    if (aData && 'duration' in aData) {\n      if (aData.duration && !(aData.duration instanceof ICAL.Duration)) {\n        throw new TypeError('.duration must be an instance of ICAL.Duration');\n      }\n      this.duration = aData.duration;\n    }\n  };\n\n  ICAL.Period.prototype = {\n\n    start: null,\n    end: null,\n    duration: null,\n    icalclass: \"icalperiod\",\n    icaltype: \"period\",\n\n    clone: function() {\n      return ICAL.Period.fromData({\n        start: this.start ? this.start.clone() : null,\n        end: this.end ? this.end.clone() : null,\n        duration: this.duration ? this.duration.clone() : null\n      });\n    },\n\n    getDuration: function duration() {\n      if (this.duration) {\n        return this.duration;\n      } else {\n        return this.end.subtractDate(this.start);\n      }\n    },\n\n    getEnd: function() {\n      if (this.end) {\n        return this.end;\n      } else {\n        var end = this.start.clone();\n        end.addDuration(this.duration);\n        return end;\n      }\n    },\n\n    toString: function toString() {\n      return this.start + \"/\" + (this.end || this.duration);\n    },\n\n    toJSON: function() {\n      return [this.start.toString(), (this.end || this.duration).toString()];\n    },\n\n    toICALString: function() {\n      return this.start.toICALString() + \"/\" +\n             (this.end || this.duration).toICALString();\n    }\n  };\n\n  ICAL.Period.fromString = function fromString(str, prop) {\n    var parts = str.split('/');\n\n    if (parts.length !== 2) {\n      throw new Error(\n        'Invalid string value: \"' + str + '\" must contain a \"/\" char.'\n      );\n    }\n\n    var options = {\n      start: ICAL.Time.fromDateTimeString(parts[0], prop)\n    };\n\n    var end = parts[1];\n\n    if (ICAL.Duration.isValueString(end)) {\n      options.duration = ICAL.Duration.fromString(end);\n    } else {\n      options.end = ICAL.Time.fromDateTimeString(end, prop);\n    }\n\n    return new ICAL.Period(options);\n  };\n\n  ICAL.Period.fromData = function fromData(aData) {\n    return new ICAL.Period(aData);\n  };\n\n  ICAL.Period.fromJSON = function(aData, aProp) {\n    if (ICAL.Duration.isValueString(aData[1])) {\n      return ICAL.Period.fromData({\n        start: ICAL.Time.fromDateTimeString(aData[0], aProp),\n        duration: ICAL.Duration.fromString(aData[1])\n      });\n    } else {\n      return ICAL.Period.fromData({\n        start: ICAL.Time.fromDateTimeString(aData[0], aProp),\n        end: ICAL.Time.fromDateTimeString(aData[1], aProp)\n      });\n    }\n  };\n})();\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2011-2012 */\n\n\n\n/* istanbul ignore next */\n(typeof(ICAL) === 'undefined') ? ICAL = {} : ''; // jshint ignore:line\n\n(function() {\n  var DURATION_LETTERS = /([PDWHMTS]{1,1})/;\n\n  ICAL.Duration = function icalduration(data) {\n    this.wrappedJSObject = this;\n    this.fromData(data);\n  };\n\n  ICAL.Duration.prototype = {\n\n    weeks: 0,\n    days: 0,\n    hours: 0,\n    minutes: 0,\n    seconds: 0,\n    isNegative: false,\n    icalclass: \"icalduration\",\n    icaltype: \"duration\",\n\n    clone: function clone() {\n      return ICAL.Duration.fromData(this);\n    },\n\n    toSeconds: function toSeconds() {\n      var seconds = this.seconds + 60 * this.minutes + 3600 * this.hours +\n                    86400 * this.days + 7 * 86400 * this.weeks;\n      return (this.isNegative ? -seconds : seconds);\n    },\n\n    fromSeconds: function fromSeconds(aSeconds) {\n      var secs = Math.abs(aSeconds);\n\n      this.isNegative = (aSeconds < 0);\n      this.days = ICAL.helpers.trunc(secs / 86400);\n\n      // If we have a flat number of weeks, use them.\n      if (this.days % 7 == 0) {\n        this.weeks = this.days / 7;\n        this.days = 0;\n      } else {\n        this.weeks = 0;\n      }\n\n      secs -= (this.days + 7 * this.weeks) * 86400;\n\n      this.hours = ICAL.helpers.trunc(secs / 3600);\n      secs -= this.hours * 3600;\n\n      this.minutes = ICAL.helpers.trunc(secs / 60);\n      secs -= this.minutes * 60;\n\n      this.seconds = secs;\n      return this;\n    },\n\n    fromData: function fromData(aData) {\n      var propsToCopy = [\"weeks\", \"days\", \"hours\",\n                         \"minutes\", \"seconds\", \"isNegative\"];\n      for (var key in propsToCopy) {\n        var prop = propsToCopy[key];\n        if (aData && prop in aData) {\n          this[prop] = aData[prop];\n        } else {\n          this[prop] = 0;\n        }\n      }\n    },\n\n    reset: function reset() {\n      this.isNegative = false;\n      this.weeks = 0;\n      this.days = 0;\n      this.hours = 0;\n      this.minutes = 0;\n      this.seconds = 0;\n    },\n\n    compare: function compare(aOther) {\n      var thisSeconds = this.toSeconds();\n      var otherSeconds = aOther.toSeconds();\n      return (thisSeconds > otherSeconds) - (thisSeconds < otherSeconds);\n    },\n\n    normalize: function normalize() {\n      this.fromSeconds(this.toSeconds());\n      return this;\n    },\n\n    toString: function toString() {\n      if (this.toSeconds() == 0) {\n        return \"PT0S\";\n      } else {\n        var str = \"\";\n        if (this.isNegative) str += \"-\";\n        str += \"P\";\n        if (this.weeks) str += this.weeks + \"W\";\n        if (this.days) str += this.days + \"D\";\n\n        if (this.hours || this.minutes || this.seconds) {\n          str += \"T\";\n          if (this.hours) str += this.hours + \"H\";\n          if (this.minutes) str += this.minutes + \"M\";\n          if (this.seconds) str += this.seconds + \"S\";\n        }\n        return str;\n      }\n    },\n\n    toICALString: function() {\n      return this.toString();\n    }\n  };\n\n  ICAL.Duration.fromSeconds = function icalduration_from_seconds(aSeconds) {\n    return (new ICAL.Duration()).fromSeconds(aSeconds);\n  };\n\n  /**\n   * Internal helper function to handle a chunk of a duration.\n   *\n   * @param {String} letter type of duration chunk.\n   * @param {String} number numeric value or -/+.\n   * @param {Object} dict target to assign values to.\n   */\n  function parseDurationChunk(letter, number, object) {\n    var type;\n    switch (letter) {\n      case 'P':\n        if (number && number === '-') {\n          object.isNegative = true;\n        } else {\n          object.isNegative = false;\n        }\n        // period\n        break;\n      case 'D':\n        type = 'days';\n        break;\n      case 'W':\n        type = 'weeks';\n        break;\n      case 'H':\n        type = 'hours';\n        break;\n      case 'M':\n        type = 'minutes';\n        break;\n      case 'S':\n        type = 'seconds';\n        break;\n      default:\n        // Not a valid chunk\n        return 0;\n    }\n\n    if (type) {\n      if (!number && number !== 0) {\n        throw new Error(\n          'invalid duration value: Missing number before \"' + letter + '\"'\n        );\n      }\n      var num = parseInt(number, 10);\n      if (ICAL.helpers.isStrictlyNaN(num)) {\n        throw new Error(\n          'invalid duration value: Invalid number \"' + number + '\" before \"' + letter + '\"'\n        );\n      }\n      object[type] = num;\n    }\n\n    return 1;\n  }\n\n  /**\n   * @param {String} value raw ical value.\n   * @return {Boolean}\n   *  true when the given value is of the duration ical type.\n   */\n  ICAL.Duration.isValueString = function(string) {\n    return (string[0] === 'P' || string[1] === 'P');\n  };\n\n  ICAL.Duration.fromString = function icalduration_from_string(aStr) {\n    var pos = 0;\n    var dict = Object.create(null);\n    var chunks = 0;\n\n    while ((pos = aStr.search(DURATION_LETTERS)) !== -1) {\n      var type = aStr[pos];\n      var numeric = aStr.substr(0, pos);\n      aStr = aStr.substr(pos + 1);\n\n      chunks += parseDurationChunk(type, numeric, dict);\n    }\n\n    if (chunks < 2) {\n      // There must be at least a chunk with \"P\" and some unit chunk\n      throw new Error(\n        'invalid duration value: Not enough duration components in \"' + aStr + '\"'\n      );\n    }\n\n    return new ICAL.Duration(dict);\n  };\n\n  ICAL.Duration.fromData = function icalduration_from_data(aData) {\n    return new ICAL.Duration(aData);\n  };\n})();\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2011-2012 */\n\n\n\n/* istanbul ignore next */\n(typeof(ICAL) === 'undefined') ? ICAL = {} : ''; // jshint ignore:line\n\n(function() {\n  var OPTIONS = [\"tzid\", \"location\", \"tznames\",\n                 \"latitude\", \"longitude\"];\n\n  /**\n   * Timezone representation, created by passing in a tzid and component.\n   *\n   *    var vcalendar;\n   *    var timezoneComp = vcalendar.getFirstSubcomponent('vtimezone');\n   *    var tzid = timezoneComp.getFirstPropertyValue('tzid');\n   *\n   *    var timezone = new ICAL.Timezone({\n   *      component: timezoneComp,\n   *      tzid\n   *    });\n   *\n   *\n   * @param {Object} data options for class (see above).\n   */\n  ICAL.Timezone = function icaltimezone(data) {\n    this.wrappedJSObject = this;\n    this.fromData(data);\n  };\n\n  ICAL.Timezone.prototype = {\n\n    tzid: \"\",\n    location: \"\",\n    tznames: \"\",\n\n    latitude: 0.0,\n    longitude: 0.0,\n\n    component: null,\n\n    expandedUntilYear: 0,\n\n    icalclass: \"icaltimezone\",\n\n    fromData: function fromData(aData) {\n      this.expandedUntilYear = 0;\n      this.changes = [];\n\n      if (aData instanceof ICAL.Component) {\n        // Either a component is passed directly\n        this.component = aData;\n      } else {\n        // Otherwise the component may be in the data object\n        if (aData && \"component\" in aData) {\n          if (typeof aData.component == \"string\") {\n            // If a string was passed, parse it as a component\n            var jCal = ICAL.parse(aData.component);\n            this.component = new ICAL.Component(jCal);\n          } else if (aData.component instanceof ICAL.Component) {\n            // If it was a component already, then just set it\n            this.component = aData.component;\n          } else {\n            // Otherwise just null out the component\n            this.component = null;\n          }\n        }\n\n        // Copy remaining passed properties\n        for (var key in OPTIONS) {\n          var prop = OPTIONS[key];\n          if (aData && prop in aData) {\n            this[prop] = aData[prop];\n          }\n        }\n      }\n\n      // If we have a component but no TZID, attempt to get it from the\n      // component's properties.\n      if (this.component instanceof ICAL.Component && !this.tzid) {\n        this.tzid = this.component.getFirstPropertyValue('tzid');\n      }\n\n      return this;\n    },\n\n    /**\n     * Finds the utcOffset the given time would occur in this timezone.\n     *\n     * @return {Number} utc offset in seconds.\n     */\n    utcOffset: function utcOffset(tt) {\n      if (this == ICAL.Timezone.utcTimezone || this == ICAL.Timezone.localTimezone) {\n        return 0;\n      }\n\n      this._ensureCoverage(tt.year);\n\n      if (!this.changes.length) {\n        return 0;\n      }\n\n      var tt_change = {\n        year: tt.year,\n        month: tt.month,\n        day: tt.day,\n        hour: tt.hour,\n        minute: tt.minute,\n        second: tt.second\n      };\n\n      var change_num = this._findNearbyChange(tt_change);\n      var change_num_to_use = -1;\n      var step = 1;\n\n      // TODO: replace with bin search?\n      for (;;) {\n        var change = ICAL.helpers.clone(this.changes[change_num], true);\n        if (change.utcOffset < change.prevUtcOffset) {\n          ICAL.Timezone.adjust_change(change, 0, 0, 0, change.utcOffset);\n        } else {\n          ICAL.Timezone.adjust_change(change, 0, 0, 0,\n                                          change.prevUtcOffset);\n        }\n\n        var cmp = ICAL.Timezone._compare_change_fn(tt_change, change);\n\n        if (cmp >= 0) {\n          change_num_to_use = change_num;\n        } else {\n          step = -1;\n        }\n\n        if (step == -1 && change_num_to_use != -1) {\n          break;\n        }\n\n        change_num += step;\n\n        if (change_num < 0) {\n          return 0;\n        }\n\n        if (change_num >= this.changes.length) {\n          break;\n        }\n      }\n\n      var zone_change = this.changes[change_num_to_use];\n      var utcOffset_change = zone_change.utcOffset - zone_change.prevUtcOffset;\n\n      if (utcOffset_change < 0 && change_num_to_use > 0) {\n        var tmp_change = ICAL.helpers.clone(zone_change, true);\n        ICAL.Timezone.adjust_change(tmp_change, 0, 0, 0,\n                                        tmp_change.prevUtcOffset);\n\n        if (ICAL.Timezone._compare_change_fn(tt_change, tmp_change) < 0) {\n          var prev_zone_change = this.changes[change_num_to_use - 1];\n\n          var want_daylight = false; // TODO\n\n          if (zone_change.is_daylight != want_daylight &&\n              prev_zone_change.is_daylight == want_daylight) {\n            zone_change = prev_zone_change;\n          }\n        }\n      }\n\n      // TODO return is_daylight?\n      return zone_change.utcOffset;\n    },\n\n    _findNearbyChange: function icaltimezone_find_nearby_change(change) {\n      // find the closest match\n      var idx = ICAL.helpers.binsearchInsert(\n        this.changes,\n        change,\n        ICAL.Timezone._compare_change_fn\n      );\n\n      if (idx >= this.changes.length) {\n        return this.changes.length - 1;\n      }\n\n      return idx;\n    },\n\n    _ensureCoverage: function(aYear) {\n      if (ICAL.Timezone._minimumExpansionYear == -1) {\n        var today = ICAL.Time.now();\n        ICAL.Timezone._minimumExpansionYear = today.year;\n      }\n\n      var changesEndYear = aYear;\n      if (changesEndYear < ICAL.Timezone._minimumExpansionYear) {\n        changesEndYear = ICAL.Timezone._minimumExpansionYear;\n      }\n\n      changesEndYear += ICAL.Timezone.EXTRA_COVERAGE;\n\n      if (changesEndYear > ICAL.Timezone.MAX_YEAR) {\n        changesEndYear = ICAL.Timezone.MAX_YEAR;\n      }\n\n      if (!this.changes.length || this.expandedUntilYear < aYear) {\n        var subcomps = this.component.getAllSubcomponents();\n        var compLen = subcomps.length;\n        var compIdx = 0;\n\n        for (; compIdx < compLen; compIdx++) {\n          this._expandComponent(\n            subcomps[compIdx], changesEndYear, this.changes\n          );\n        }\n\n        this.changes.sort(ICAL.Timezone._compare_change_fn);\n        this.expandedUntilYear = changesEndYear;\n      }\n    },\n\n    _expandComponent: function(aComponent, aYear, changes) {\n      if (!aComponent.hasProperty(\"dtstart\") ||\n          !aComponent.hasProperty(\"tzoffsetto\") ||\n          !aComponent.hasProperty(\"tzoffsetfrom\")) {\n        return null;\n      }\n\n      var dtstart = aComponent.getFirstProperty(\"dtstart\").getFirstValue();\n      var change;\n\n      function convert_tzoffset(offset) {\n        return offset.factor * (offset.hours * 3600 + offset.minutes * 60);\n      }\n\n      function init_changes() {\n        var changebase = {};\n        changebase.is_daylight = (aComponent.name == \"daylight\");\n        changebase.utcOffset = convert_tzoffset(\n          aComponent.getFirstProperty(\"tzoffsetto\").getFirstValue()\n        );\n\n        changebase.prevUtcOffset = convert_tzoffset(\n          aComponent.getFirstProperty(\"tzoffsetfrom\").getFirstValue()\n        );\n\n        return changebase;\n      }\n\n      if (!aComponent.hasProperty(\"rrule\") && !aComponent.hasProperty(\"rdate\")) {\n        change = init_changes();\n        change.year = dtstart.year;\n        change.month = dtstart.month;\n        change.day = dtstart.day;\n        change.hour = dtstart.hour;\n        change.minute = dtstart.minute;\n        change.second = dtstart.second;\n\n        ICAL.Timezone.adjust_change(change, 0, 0, 0,\n                                        -change.prevUtcOffset);\n        changes.push(change);\n      } else {\n        var props = aComponent.getAllProperties(\"rdate\");\n        for (var rdatekey in props) {\n          var rdate = props[rdatekey];\n          var time = rdate.getFirstValue();\n          change = init_changes();\n\n          change.year = time.year;\n          change.month = time.month;\n          change.day = time.day;\n\n          if (time.isDate) {\n            change.hour = dtstart.hour;\n            change.minute = dtstart.minute;\n            change.second = dtstart.second;\n\n            if (dtstart.zone != ICAL.Timezone.utcTimezone) {\n              ICAL.Timezone.adjust_change(change, 0, 0, 0,\n                                              -change.prevUtcOffset);\n            }\n          } else {\n            change.hour = time.hour;\n            change.minute = time.minute;\n            change.second = time.second;\n\n            if (time.zone != ICAL.Timezone.utcTimezone) {\n              ICAL.Timezone.adjust_change(change, 0, 0, 0,\n                                              -change.prevUtcOffset);\n            }\n          }\n\n          changes.push(change);\n        }\n\n        var rrule = aComponent.getFirstProperty(\"rrule\");\n\n        if (rrule) {\n          rrule = rrule.getFirstValue();\n          change = init_changes();\n\n          if (rrule.until && rrule.until.zone == ICAL.Timezone.utcTimezone) {\n            rrule.until.adjust(0, 0, 0, change.prevUtcOffset);\n            rrule.until.zone = ICAL.Timezone.localTimezone;\n          }\n\n          var iterator = rrule.iterator(dtstart);\n\n          var occ;\n          while ((occ = iterator.next())) {\n            change = init_changes();\n            if (occ.year > aYear || !occ) {\n              break;\n            }\n\n            change.year = occ.year;\n            change.month = occ.month;\n            change.day = occ.day;\n            change.hour = occ.hour;\n            change.minute = occ.minute;\n            change.second = occ.second;\n            change.isDate = occ.isDate;\n\n            ICAL.Timezone.adjust_change(change, 0, 0, 0,\n                                            -change.prevUtcOffset);\n            changes.push(change);\n          }\n        }\n      }\n\n      return changes;\n    },\n\n    toString: function toString() {\n      return (this.tznames ? this.tznames : this.tzid);\n    }\n\n  };\n\n  ICAL.Timezone._compare_change_fn = function icaltimezone_compare_change_fn(a, b) {\n    if (a.year < b.year) return -1;\n    else if (a.year > b.year) return 1;\n\n    if (a.month < b.month) return -1;\n    else if (a.month > b.month) return 1;\n\n    if (a.day < b.day) return -1;\n    else if (a.day > b.day) return 1;\n\n    if (a.hour < b.hour) return -1;\n    else if (a.hour > b.hour) return 1;\n\n    if (a.minute < b.minute) return -1;\n    else if (a.minute > b.minute) return 1;\n\n    if (a.second < b.second) return -1;\n    else if (a.second > b.second) return 1;\n\n    return 0;\n  };\n\n  ICAL.Timezone.convert_time = function icaltimezone_convert_time(tt, from_zone, to_zone) {\n    if (tt.isDate ||\n        from_zone.tzid == to_zone.tzid ||\n        from_zone == ICAL.Timezone.localTimezone ||\n        to_zone == ICAL.Timezone.localTimezone) {\n      tt.zone = to_zone;\n      return tt;\n    }\n\n    var utcOffset = from_zone.utcOffset(tt);\n    tt.adjust(0, 0, 0, - utcOffset);\n\n    utcOffset = to_zone.utcOffset(tt);\n    tt.adjust(0, 0, 0, utcOffset);\n\n    return null;\n  };\n\n  ICAL.Timezone.fromData = function icaltimezone_fromData(aData) {\n    var tt = new ICAL.Timezone();\n    return tt.fromData(aData);\n  };\n\n  ICAL.Timezone.utcTimezone = ICAL.Timezone.fromData({\n    tzid: \"UTC\"\n  });\n\n  ICAL.Timezone.localTimezone = ICAL.Timezone.fromData({\n    tzid: \"floating\"\n  });\n\n  ICAL.Timezone.adjust_change = function icaltimezone_adjust_change(change, days, hours, minutes, seconds) {\n    return ICAL.Time.prototype.adjust.call(\n      change,\n      days,\n      hours,\n      minutes,\n      seconds,\n      change\n    );\n  };\n\n  ICAL.Timezone._minimumExpansionYear = -1;\n  ICAL.Timezone.MAX_YEAR = 2035; // TODO this is because of time_t, which we don't need. Still usefull?\n  ICAL.Timezone.EXTRA_COVERAGE = 5;\n})();\n// singleton class to contain timezones.\n// Right now its all manual registry in the\n// future we may use this class to download timezone\n// information or handle loading pre-expanded timezones.\nICAL.TimezoneService = (function() {\n  var zones;\n\n  // Using var rather then return so we don't need to name the functions twice.\n  // TimezoneService#get will appear in profiler, etc...\n  var TimezoneService = {\n    reset: function() {\n      zones = Object.create(null);\n      var utc = ICAL.Timezone.utcTimezone;\n\n      zones.Z = utc;\n      zones.UTC = utc;\n      zones.GMT = utc;\n    },\n\n    /**\n     * Checks if timezone id has been registered.\n     *\n     * @param {String} tzid (e.g. America/Los_Angeles).\n     * @return {Boolean} false when not present.\n     */\n    has: function(tzid) {\n      return !!zones[tzid];\n    },\n\n    /**\n     * Returns a timezone by its tzid if present.\n     *\n     * @param {String} tzid name of timezone (e.g. America/Los_Angeles).\n     * @return {ICAL.Timezone|Null} zone or null.\n     */\n    get: function(tzid) {\n      return zones[tzid];\n    },\n\n    /**\n     * Registers a timezone object or component.\n     *\n     * @param {String} [name] optional uses timezone.tzid by default.\n     * @param {ICAL.Component|ICAL.Timezone} zone initialized zone or vtimezone.\n     */\n    register: function(name, timezone) {\n      if (name instanceof ICAL.Component) {\n        if (name.name === 'vtimezone') {\n          timezone = new ICAL.Timezone(name);\n          name = timezone.tzid;\n        }\n      }\n\n      if (timezone instanceof ICAL.Timezone) {\n        zones[name] = timezone;\n      } else {\n        throw new TypeError('timezone must be ICAL.Timezone or ICAL.Component');\n      }\n    },\n\n    /**\n     * Removes a timezone by its tzid from the list.\n     *\n     * @param {String} tzid (e.g. America/Los_Angeles).\n     */\n    remove: function(tzid) {\n      return (delete zones[tzid]);\n    }\n  };\n\n  // initialize defaults\n  TimezoneService.reset();\n\n  return TimezoneService;\n}());\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2011-2015 */\n\n\n\n/* istanbul ignore next */\n(typeof(ICAL) === 'undefined') ? ICAL = {} : ''; // jshint ignore:line\n\n(function() {\n\n  /**\n   * Time representation (similar to JS Date object).\n   * Fully independent of system (OS) timezone / time.\n   * Unlike JS Date month start at 1 (Jan) not zero.\n   *\n   *\n   *    var time = new ICAL.Time({\n   *      year: 2012,\n   *      month: 10,\n   *      day: 11\n   *      minute: 0,\n   *      second: 0,\n   *      isDate: false\n   *    });\n   *\n   *\n   * @param {Object} data initialization time.\n   * @param {ICAL.Timezone} zone timezone this position occurs in.\n   */\n  ICAL.Time = function icaltime(data, zone) {\n    this.wrappedJSObject = this;\n    var time = this._time = Object.create(null);\n\n    /* time defaults */\n    time.year = 0;\n    time.month = 1;\n    time.day = 1;\n    time.hour = 0;\n    time.minute = 0;\n    time.second = 0;\n    time.isDate = false;\n\n    this.fromData(data, zone);\n  };\n\n  ICAL.Time._dowCache = {};\n  ICAL.Time._wnCache = {};\n\n  ICAL.Time.prototype = {\n\n    icalclass: \"icaltime\",\n    _cachedUnixTime: null,\n\n    // is read only strictly defined by isDate\n    get icaltype() {\n      return this.isDate ? 'date' : 'date-time';\n    },\n\n    /**\n     * @type {ICAL.Timezone}\n     */\n    zone: null,\n\n    /**\n     * Internal uses to indicate that a change has been\n     * made and the next read operation must attempt to\n     * normalize the value (for example changing the day to 33).\n     *\n     * @type {Boolean}\n     * @private\n     */\n    _pendingNormalization: false,\n\n    clone: function icaltime_clone() {\n      return new ICAL.Time(this._time, this.zone);\n    },\n\n    reset: function icaltime_reset() {\n      this.fromData(ICAL.Time.epochTime);\n      this.zone = ICAL.Timezone.utcTimezone;\n    },\n\n    resetTo: function icaltime_resetTo(year, month, day,\n                                       hour, minute, second, timezone) {\n      this.fromData({\n        year: year,\n        month: month,\n        day: day,\n        hour: hour,\n        minute: minute,\n        second: second,\n        zone: timezone\n      });\n    },\n\n    fromJSDate: function icaltime_fromJSDate(aDate, useUTC) {\n      if (!aDate) {\n        this.reset();\n      } else {\n        if (useUTC) {\n          this.zone = ICAL.Timezone.utcTimezone;\n          this.year = aDate.getUTCFullYear();\n          this.month = aDate.getUTCMonth() + 1;\n          this.day = aDate.getUTCDate();\n          this.hour = aDate.getUTCHours();\n          this.minute = aDate.getUTCMinutes();\n          this.second = aDate.getUTCSeconds();\n        } else {\n          this.zone = ICAL.Timezone.localTimezone;\n          this.year = aDate.getFullYear();\n          this.month = aDate.getMonth() + 1;\n          this.day = aDate.getDate();\n          this.hour = aDate.getHours();\n          this.minute = aDate.getMinutes();\n          this.second = aDate.getSeconds();\n        }\n      }\n      this._cachedUnixTime = null;\n      return this;\n    },\n\n    fromData: function fromData(aData, aZone) {\n      if (aData) {\n        for (var key in aData) {\n          // ical type cannot be set\n          if (key === 'icaltype') continue;\n          this[key] = aData[key];\n        }\n      }\n\n      if (aZone) {\n        this.zone = aZone;\n      }\n\n      if (aData && !(\"isDate\" in aData)) {\n        this.isDate = !(\"hour\" in aData);\n      } else if (aData && (\"isDate\" in aData)) {\n        this.isDate = aData.isDate;\n      }\n\n      if (aData && \"timezone\" in aData) {\n        var zone = ICAL.TimezoneService.get(\n          aData.timezone\n        );\n\n        this.zone = zone || ICAL.Timezone.localTimezone;\n      }\n\n      if (aData && \"zone\" in aData) {\n        this.zone = aData.zone;\n      }\n\n      if (!this.zone) {\n        this.zone = ICAL.Timezone.localTimezone;\n      }\n\n      this._cachedUnixTime = null;\n      return this;\n    },\n\n    dayOfWeek: function icaltime_dayOfWeek() {\n      var dowCacheKey = (this.year << 9) + (this.month << 5) + this.day;\n      if (dowCacheKey in ICAL.Time._dowCache) {\n        return ICAL.Time._dowCache[dowCacheKey];\n      }\n\n      // Using Zeller's algorithm\n      var q = this.day;\n      var m = this.month + (this.month < 3 ? 12 : 0);\n      var Y = this.year - (this.month < 3 ? 1 : 0);\n\n      var h = (q + Y + ICAL.helpers.trunc(((m + 1) * 26) / 10) + ICAL.helpers.trunc(Y / 4));\n      /* istanbul ignore else */\n      if (true /* gregorian */) {\n        h += ICAL.helpers.trunc(Y / 100) * 6 + ICAL.helpers.trunc(Y / 400);\n      } else {\n        h += 5;\n      }\n\n      // Normalize to 1 = sunday\n      h = ((h + 6) % 7) + 1;\n      ICAL.Time._dowCache[dowCacheKey] = h;\n      return h;\n    },\n\n    dayOfYear: function dayOfYear() {\n      var is_leap = (ICAL.Time.isLeapYear(this.year) ? 1 : 0);\n      var diypm = ICAL.Time._daysInYearPassedMontgh;\n      return diypm[is_leap][this.month - 1] + this.day;\n    },\n\n    startOfWeek: function startOfWeek(aWeekStart) {\n      var firstDow = aWeekStart || ICAL.Time.SUNDAY;\n      var result = this.clone();\n      result.day -= ((this.dayOfWeek() + 7 - firstDow) % 7);\n      result.isDate = true;\n      result.hour = 0;\n      result.minute = 0;\n      result.second = 0;\n      return result;\n    },\n\n    endOfWeek: function endOfWeek(aWeekStart) {\n      var firstDow = aWeekStart || ICAL.Time.SUNDAY;\n      var result = this.clone();\n      result.day += (7 - this.dayOfWeek() + firstDow - ICAL.Time.SUNDAY) % 7;\n      result.isDate = true;\n      result.hour = 0;\n      result.minute = 0;\n      result.second = 0;\n      return result;\n    },\n\n    startOfMonth: function startOfMonth() {\n      var result = this.clone();\n      result.day = 1;\n      result.isDate = true;\n      result.hour = 0;\n      result.minute = 0;\n      result.second = 0;\n      return result;\n    },\n\n    endOfMonth: function endOfMonth() {\n      var result = this.clone();\n      result.day = ICAL.Time.daysInMonth(result.month, result.year);\n      result.isDate = true;\n      result.hour = 0;\n      result.minute = 0;\n      result.second = 0;\n      return result;\n    },\n\n    startOfYear: function startOfYear() {\n      var result = this.clone();\n      result.day = 1;\n      result.month = 1;\n      result.isDate = true;\n      result.hour = 0;\n      result.minute = 0;\n      result.second = 0;\n      return result;\n    },\n\n    endOfYear: function endOfYear() {\n      var result = this.clone();\n      result.day = 31;\n      result.month = 12;\n      result.isDate = true;\n      result.hour = 0;\n      result.minute = 0;\n      result.second = 0;\n      return result;\n    },\n\n    startDoyWeek: function startDoyWeek(aFirstDayOfWeek) {\n      var firstDow = aFirstDayOfWeek || ICAL.Time.SUNDAY;\n      var delta = this.dayOfWeek() - firstDow;\n      if (delta < 0) delta += 7;\n      return this.dayOfYear() - delta;\n    },\n\n    /**\n     * Finds the nthWeekDay relative to the current month (not day).\n     * The returned value is a day relative the month that this\n     * month belongs to so 1 would indicate the first of the month\n     * and 40 would indicate a day in the following month.\n     *\n     * @param {Numeric} aDayOfWeek day of the week see the day name constants.\n     * @param {Numeric} aPos nth occurrence of a given week day\n     *                       values of 1 and 0 both indicate the first\n     *                       weekday of that type. aPos may be either positive\n     *                       or negative.\n     *\n     * @return {Numeric} numeric value indicating a day relative\n     *                   to the current month of this time object.\n     */\n    nthWeekDay: function icaltime_nthWeekDay(aDayOfWeek, aPos) {\n      var daysInMonth = ICAL.Time.daysInMonth(this.month, this.year);\n      var weekday;\n      var pos = aPos;\n\n      var start = 0;\n\n      var otherDay = this.clone();\n\n      if (pos >= 0) {\n        otherDay.day = 1;\n\n        // because 0 means no position has been given\n        // 1 and 0 indicate the same day.\n        if (pos != 0) {\n          // remove the extra numeric value\n          pos--;\n        }\n\n        // set current start offset to current day.\n        start = otherDay.day;\n\n        // find the current day of week\n        var startDow = otherDay.dayOfWeek();\n\n        // calculate the difference between current\n        // day of the week and desired day of the week\n        var offset = aDayOfWeek - startDow;\n\n\n        // if the offset goes into the past\n        // week we add 7 so its goes into the next\n        // week. We only want to go forward in time here.\n        if (offset < 0)\n          // this is really important otherwise we would\n          // end up with dates from in the past.\n          offset += 7;\n\n        // add offset to start so start is the same\n        // day of the week as the desired day of week.\n        start += offset;\n\n        // because we are going to add (and multiply)\n        // the numeric value of the day we subtract it\n        // from the start position so not to add it twice.\n        start -= aDayOfWeek;\n\n        // set week day\n        weekday = aDayOfWeek;\n      } else {\n\n        // then we set it to the last day in the current month\n        otherDay.day = daysInMonth;\n\n        // find the ends weekday\n        var endDow = otherDay.dayOfWeek();\n\n        pos++;\n\n        weekday = (endDow - aDayOfWeek);\n\n        if (weekday < 0) {\n          weekday += 7;\n        }\n\n        weekday = daysInMonth - weekday;\n      }\n\n      weekday += pos * 7;\n\n      return start + weekday;\n    },\n\n    /**\n     * Checks if current time is the nthWeekDay.\n     * Relative to the current month.\n     *\n     * Will always return false when rule resolves\n     * outside of current month.\n     *\n     * @param {Numeric} aDayOfWeek day of week.\n     * @param {Numeric} aPos position.\n     * @param {Numeric} aMax maximum valid day.\n     */\n    isNthWeekDay: function(aDayOfWeek, aPos) {\n      var dow = this.dayOfWeek();\n\n      if (aPos === 0 && dow === aDayOfWeek) {\n        return true;\n      }\n\n      // get pos\n      var day = this.nthWeekDay(aDayOfWeek, aPos);\n\n      if (day === this.day) {\n        return true;\n      }\n\n      return false;\n    },\n\n    weekNumber: function weekNumber(aWeekStart) {\n      var wnCacheKey = (this.year << 12) + (this.month << 8) + (this.day << 3) + aWeekStart;\n      if (wnCacheKey in ICAL.Time._wnCache) {\n        return ICAL.Time._wnCache[wnCacheKey];\n      }\n      // This function courtesty of Julian Bucknall, published under the MIT license\n      // http://www.boyet.com/articles/publishedarticles/calculatingtheisoweeknumb.html\n      var doy = this.dayOfYear();\n      var dow = this.dayOfWeek();\n      var year = this.year;\n      var week1;\n\n      var dt = this.clone();\n      dt.isDate = true;\n      var first_dow = dt.dayOfWeek();\n      var isoyear = this.year;\n\n      if (dt.month == 12 && dt.day > 28) {\n        week1 = ICAL.Time.weekOneStarts(isoyear + 1, aWeekStart);\n        if (dt.compare(week1) < 0) {\n          week1 = ICAL.Time.weekOneStarts(isoyear, aWeekStart);\n        } else {\n          isoyear++;\n        }\n      } else {\n        week1 = ICAL.Time.weekOneStarts(isoyear, aWeekStart);\n        if (dt.compare(week1) < 0) {\n          week1 = ICAL.Time.weekOneStarts(--isoyear, aWeekStart);\n        }\n      }\n\n      var daysBetween = (dt.subtractDate(week1).toSeconds() / 86400);\n      var answer = ICAL.helpers.trunc(daysBetween / 7) + 1;\n      ICAL.Time._wnCache[wnCacheKey] = answer;\n      return answer;\n    },\n\n    addDuration: function icaltime_add(aDuration) {\n      var mult = (aDuration.isNegative ? -1 : 1);\n\n      // because of the duration optimizations it is much\n      // more efficient to grab all the values up front\n      // then set them directly (which will avoid a normalization call).\n      // So we don't actually normalize until we need it.\n      var second = this.second;\n      var minute = this.minute;\n      var hour = this.hour;\n      var day = this.day;\n\n      second += mult * aDuration.seconds;\n      minute += mult * aDuration.minutes;\n      hour += mult * aDuration.hours;\n      day += mult * aDuration.days;\n      day += mult * 7 * aDuration.weeks;\n\n      this.second = second;\n      this.minute = minute;\n      this.hour = hour;\n      this.day = day;\n\n      this._cachedUnixTime = null;\n    },\n\n    /**\n     * Subtract the date details (_excluding_ timezone).\n     * Useful for finding the relative difference between\n     * two time objects excluding their timezone differences.\n     *\n     * @return {ICAL.Duration} difference in duration.\n     */\n    subtractDate: function icaltime_subtract(aDate) {\n      var unixTime = this.toUnixTime() + this.utcOffset();\n      var other = aDate.toUnixTime() + aDate.utcOffset();\n      return ICAL.Duration.fromSeconds(unixTime - other);\n    },\n\n    /**\n     * Subtract the date details, taking timezones into account.\n     *\n     * @param {ICAL.Time}  The date to subtract.\n     * @return {ICAL.Duration}  The difference in duration.\n     */\n    subtractDateTz: function icaltime_subtract_abs(aDate) {\n      var unixTime = this.toUnixTime();\n      var other = aDate.toUnixTime();\n      return ICAL.Duration.fromSeconds(unixTime - other);\n    },\n\n    compare: function icaltime_compare(other) {\n      var a = this.toUnixTime();\n      var b = other.toUnixTime();\n\n      if (a > b) return 1;\n      if (b > a) return -1;\n      return 0;\n    },\n\n    compareDateOnlyTz: function icaltime_compareDateOnlyTz(other, tz) {\n      function cmp(attr) {\n        return ICAL.Time._cmp_attr(a, b, attr);\n      }\n      var a = this.convertToZone(tz);\n      var b = other.convertToZone(tz);\n      var rc = 0;\n\n      if ((rc = cmp(\"year\")) != 0) return rc;\n      if ((rc = cmp(\"month\")) != 0) return rc;\n      if ((rc = cmp(\"day\")) != 0) return rc;\n\n      return rc;\n    },\n\n    convertToZone: function convertToZone(zone) {\n      var copy = this.clone();\n      var zone_equals = (this.zone.tzid == zone.tzid);\n\n      if (!this.isDate && !zone_equals) {\n        ICAL.Timezone.convert_time(copy, this.zone, zone);\n      }\n\n      copy.zone = zone;\n      return copy;\n    },\n\n    utcOffset: function utc_offset() {\n      if (this.zone == ICAL.Timezone.localTimezone ||\n          this.zone == ICAL.Timezone.utcTimezone) {\n        return 0;\n      } else {\n        return this.zone.utcOffset(this);\n      }\n    },\n\n    /**\n     * Returns an RFC 5455 compliant ical representation of this object.\n     *\n     * @return {String} ical date/date-time.\n     */\n    toICALString: function() {\n      var string = this.toString();\n\n      if (string.length > 10) {\n        return ICAL.design.icalendar.value['date-time'].toICAL(string);\n      } else {\n        return ICAL.design.icalendar.value.date.toICAL(string);\n      }\n    },\n\n    toString: function toString() {\n      var result = this.year + '-' +\n                   ICAL.helpers.pad2(this.month) + '-' +\n                   ICAL.helpers.pad2(this.day);\n\n      if (!this.isDate) {\n          result += 'T' + ICAL.helpers.pad2(this.hour) + ':' +\n                    ICAL.helpers.pad2(this.minute) + ':' +\n                    ICAL.helpers.pad2(this.second);\n\n        if (this.zone === ICAL.Timezone.utcTimezone) {\n          result += 'Z';\n        }\n      }\n\n      return result;\n    },\n\n    toJSDate: function toJSDate() {\n      if (this.zone == ICAL.Timezone.localTimezone) {\n        if (this.isDate) {\n          return new Date(this.year, this.month - 1, this.day);\n        } else {\n          return new Date(this.year, this.month - 1, this.day,\n                          this.hour, this.minute, this.second, 0);\n        }\n      } else {\n        return new Date(this.toUnixTime() * 1000);\n      }\n    },\n\n    _normalize: function icaltime_normalize() {\n      var isDate = this._time.isDate;\n      if (this._time.isDate) {\n        this._time.hour = 0;\n        this._time.minute = 0;\n        this._time.second = 0;\n      }\n      this.adjust(0, 0, 0, 0);\n\n      return this;\n    },\n\n    adjust: function icaltime_adjust(aExtraDays, aExtraHours,\n                                     aExtraMinutes, aExtraSeconds, aTime) {\n\n      var minutesOverflow, hoursOverflow,\n          daysOverflow = 0, yearsOverflow = 0;\n\n      var second, minute, hour, day;\n      var daysInMonth;\n\n      var time = aTime || this._time;\n\n      if (!time.isDate) {\n        second = time.second + aExtraSeconds;\n        time.second = second % 60;\n        minutesOverflow = ICAL.helpers.trunc(second / 60);\n        if (time.second < 0) {\n          time.second += 60;\n          minutesOverflow--;\n        }\n\n        minute = time.minute + aExtraMinutes + minutesOverflow;\n        time.minute = minute % 60;\n        hoursOverflow = ICAL.helpers.trunc(minute / 60);\n        if (time.minute < 0) {\n          time.minute += 60;\n          hoursOverflow--;\n        }\n\n        hour = time.hour + aExtraHours + hoursOverflow;\n\n        time.hour = hour % 24;\n        daysOverflow = ICAL.helpers.trunc(hour / 24);\n        if (time.hour < 0) {\n          time.hour += 24;\n          daysOverflow--;\n        }\n      }\n\n\n      // Adjust month and year first, because we need to know what month the day\n      // is in before adjusting it.\n      if (time.month > 12) {\n        yearsOverflow = ICAL.helpers.trunc((time.month - 1) / 12);\n      } else if (time.month < 1) {\n        yearsOverflow = ICAL.helpers.trunc(time.month / 12) - 1;\n      }\n\n      time.year += yearsOverflow;\n      time.month -= 12 * yearsOverflow;\n\n      // Now take care of the days (and adjust month if needed)\n      day = time.day + aExtraDays + daysOverflow;\n\n      if (day > 0) {\n        for (;;) {\n          daysInMonth = ICAL.Time.daysInMonth(time.month, time.year);\n          if (day <= daysInMonth) {\n            break;\n          }\n\n          time.month++;\n          if (time.month > 12) {\n            time.year++;\n            time.month = 1;\n          }\n\n          day -= daysInMonth;\n        }\n      } else {\n        while (day <= 0) {\n          if (time.month == 1) {\n            time.year--;\n            time.month = 12;\n          } else {\n            time.month--;\n          }\n\n          day += ICAL.Time.daysInMonth(time.month, time.year);\n        }\n      }\n\n      time.day = day;\n\n      this._cachedUnixTime = null;\n      return this;\n    },\n\n    fromUnixTime: function fromUnixTime(seconds) {\n      this.zone = ICAL.Timezone.utcTimezone;\n      var epoch = ICAL.Time.epochTime.clone();\n      epoch.adjust(0, 0, 0, seconds);\n\n      this.year = epoch.year;\n      this.month = epoch.month;\n      this.day = epoch.day;\n      this.hour = epoch.hour;\n      this.minute = epoch.minute;\n      this.second = Math.floor(epoch.second);\n\n      this._cachedUnixTime = null;\n    },\n\n    toUnixTime: function toUnixTime() {\n      if (this._cachedUnixTime !== null) {\n        return this._cachedUnixTime;\n      }\n      var offset = this.utcOffset();\n\n      // we use the offset trick to ensure\n      // that we are getting the actual UTC time\n      var ms = Date.UTC(\n        this.year,\n        this.month - 1,\n        this.day,\n        this.hour,\n        this.minute,\n        this.second - offset\n      );\n\n      // seconds\n      this._cachedUnixTime = ms / 1000;\n      return this._cachedUnixTime;\n    },\n\n    /**\n     * Converts time to into Object\n     * which can be serialized then re-created\n     * using the constructor.\n     *\n     * Example:\n     *\n     *    // toJSON will automatically be called\n     *    var json = JSON.stringify(mytime);\n     *\n     *    var deserialized = JSON.parse(json);\n     *\n     *    var time = new ICAL.Time(deserialized);\n     *\n     */\n    toJSON: function() {\n      var copy = [\n        'year',\n        'month',\n        'day',\n        'hour',\n        'minute',\n        'second',\n        'isDate'\n      ];\n\n      var result = Object.create(null);\n\n      var i = 0;\n      var len = copy.length;\n      var prop;\n\n      for (; i < len; i++) {\n        prop = copy[i];\n        result[prop] = this[prop];\n      }\n\n      if (this.zone) {\n        result.timezone = this.zone.tzid;\n      }\n\n      return result;\n    }\n\n  };\n\n  (function setupNormalizeAttributes() {\n    // This needs to run before any instances are created!\n    function defineAttr(attr) {\n      Object.defineProperty(ICAL.Time.prototype, attr, {\n        get: function getTimeAttr() {\n          if (this._pendingNormalization) {\n            this._normalize();\n            this._pendingNormalization = false;\n          }\n\n          return this._time[attr];\n        },\n        set: function setTimeAttr(val) {\n          this._cachedUnixTime = null;\n          this._pendingNormalization = true;\n          this._time[attr] = val;\n\n          return val;\n        }\n      });\n\n    }\n\n    /* istanbul ignore else */\n    if (\"defineProperty\" in Object) {\n      defineAttr(\"year\");\n      defineAttr(\"month\");\n      defineAttr(\"day\");\n      defineAttr(\"hour\");\n      defineAttr(\"minute\");\n      defineAttr(\"second\");\n      defineAttr(\"isDate\");\n    }\n  })();\n\n  ICAL.Time.daysInMonth = function icaltime_daysInMonth(month, year) {\n    var _daysInMonth = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n    var days = 30;\n\n    if (month < 1 || month > 12) return days;\n\n    days = _daysInMonth[month];\n\n    if (month == 2) {\n      days += ICAL.Time.isLeapYear(year);\n    }\n\n    return days;\n  };\n\n  ICAL.Time.isLeapYear = function isLeapYear(year) {\n    if (year <= 1752) {\n      return ((year % 4) == 0);\n    } else {\n      return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));\n    }\n  };\n\n  ICAL.Time.fromDayOfYear = function icaltime_fromDayOfYear(aDayOfYear, aYear) {\n    var year = aYear;\n    var doy = aDayOfYear;\n    var tt = new ICAL.Time();\n    tt.auto_normalize = false;\n    var is_leap = (ICAL.Time.isLeapYear(year) ? 1 : 0);\n\n    if (doy < 1) {\n      year--;\n      is_leap = (ICAL.Time.isLeapYear(year) ? 1 : 0);\n      doy += ICAL.Time._daysInYearPassedMontgh[is_leap][12];\n      return ICAL.Time.fromDayOfYear(doy, year);\n    } else if (doy > ICAL.Time._daysInYearPassedMontgh[is_leap][12]) {\n      is_leap = (ICAL.Time.isLeapYear(year) ? 1 : 0);\n      doy -= ICAL.Time._daysInYearPassedMontgh[is_leap][12];\n      year++;\n      return ICAL.Time.fromDayOfYear(doy, year);\n    }\n\n    tt.year = year;\n    tt.isDate = true;\n\n    for (var month = 11; month >= 0; month--) {\n      if (doy > ICAL.Time._daysInYearPassedMontgh[is_leap][month]) {\n        tt.month = month + 1;\n        tt.day = doy - ICAL.Time._daysInYearPassedMontgh[is_leap][month];\n        break;\n      }\n    }\n\n    tt.auto_normalize = true;\n    return tt;\n  };\n\n  ICAL.Time.fromStringv2 = function fromString(str) {\n    return new ICAL.Time({\n      year: parseInt(str.substr(0, 4), 10),\n      month: parseInt(str.substr(5, 2), 10),\n      day: parseInt(str.substr(8, 2), 10),\n      isDate: true\n    });\n  };\n\n  ICAL.Time.fromDateString = function(aValue, aProp) {\n    // Dates should have no timezone.\n    // Google likes to sometimes specify Z on dates\n    // we specifically ignore that to avoid issues.\n\n    // YYYY-MM-DD\n    // 2012-10-10\n    return new ICAL.Time({\n      year: ICAL.helpers.strictParseInt(aValue.substr(0, 4)),\n      month: ICAL.helpers.strictParseInt(aValue.substr(5, 2)),\n      day: ICAL.helpers.strictParseInt(aValue.substr(8, 2)),\n      isDate: true\n    });\n  };\n\n  ICAL.Time.fromDateTimeString = function(aValue, prop) {\n    if (aValue.length < 19) {\n      throw new Error(\n        'invalid date-time value: \"' + aValue + '\"'\n      );\n    }\n\n    var zone;\n\n    if (aValue[19] === 'Z') {\n      zone = 'Z';\n    } else if (prop) {\n      zone = prop.getParameter('tzid');\n    }\n\n    // 2012-10-10T10:10:10(Z)?\n    var time = new ICAL.Time({\n      year: ICAL.helpers.strictParseInt(aValue.substr(0, 4)),\n      month: ICAL.helpers.strictParseInt(aValue.substr(5, 2)),\n      day: ICAL.helpers.strictParseInt(aValue.substr(8, 2)),\n      hour: ICAL.helpers.strictParseInt(aValue.substr(11, 2)),\n      minute: ICAL.helpers.strictParseInt(aValue.substr(14, 2)),\n      second: ICAL.helpers.strictParseInt(aValue.substr(17, 2)),\n      timezone: zone\n    });\n\n    return time;\n  };\n\n  ICAL.Time.fromString = function fromString(aValue) {\n    if (aValue.length > 10) {\n      return ICAL.Time.fromDateTimeString(aValue);\n    } else {\n      return ICAL.Time.fromDateString(aValue);\n    }\n  };\n\n  ICAL.Time.fromJSDate = function fromJSDate(aDate, useUTC) {\n    var tt = new ICAL.Time();\n    return tt.fromJSDate(aDate, useUTC);\n  };\n\n  ICAL.Time.fromData = function fromData(aData) {\n    var t = new ICAL.Time();\n    return t.fromData(aData);\n  };\n\n  ICAL.Time.now = function icaltime_now() {\n    return ICAL.Time.fromJSDate(new Date(), false);\n  };\n\n  ICAL.Time.weekOneStarts = function weekOneStarts(aYear, aWeekStart) {\n    var t = ICAL.Time.fromData({\n      year: aYear,\n      month: 1,\n      day: 4,\n      isDate: true\n    });\n\n    var fourth_dow = t.dayOfWeek();\n    t.day += (1 - fourth_dow) + ((aWeekStart || ICAL.Time.SUNDAY) - 1);\n    return t;\n  };\n\n  ICAL.Time.epochTime = ICAL.Time.fromData({\n    year: 1970,\n    month: 1,\n    day: 1,\n    hour: 0,\n    minute: 0,\n    second: 0,\n    isDate: false,\n    timezone: \"Z\"\n  });\n\n  ICAL.Time._cmp_attr = function _cmp_attr(a, b, attr) {\n    if (a[attr] > b[attr]) return 1;\n    if (a[attr] < b[attr]) return -1;\n    return 0;\n  };\n\n  ICAL.Time._daysInYearPassedMontgh = [\n    [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],\n    [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]\n  ];\n\n\n  ICAL.Time.SUNDAY = 1;\n  ICAL.Time.MONDAY = 2;\n  ICAL.Time.TUESDAY = 3;\n  ICAL.Time.WEDNESDAY = 4;\n  ICAL.Time.THURSDAY = 5;\n  ICAL.Time.FRIDAY = 6;\n  ICAL.Time.SATURDAY = 7;\n\n  ICAL.Time.DEFAULT_WEEK_START = ICAL.Time.MONDAY;\n})();\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2015 */\n\n\n\n/* istanbul ignore next */\n(typeof(ICAL) === 'undefined') ? ICAL = {} : ''; // jshint ignore:line\n\n(function() {\n\n  /**\n   * Describes a vCard time, which has slight differences to the ICAL.Time.\n   * Properties can be null if not specified, for example for dates with\n   * reduced accuracy or truncation.\n   *\n   * Note that currently not all methods are correctly re-implemented for\n   * VCardTime. For example, comparison will have undefined results when some\n   * members are null.\n   *\n   * Also, normalization is not yet implemented for this class!\n   *\n   * @param {Object} data                           The data for the time instance.\n   * @param {ICAL.Timezone|ICAL.UtcOffset} zone     The timezone to use\n   * @param {String} icaltype                       The type for this date/time object.\n   */\n  ICAL.VCardTime = function(data, zone, icaltype) {\n    this.wrappedJSObject = this;\n    var time = this._time = Object.create(null);\n\n    time.year = null;\n    time.month = null;\n    time.day = null;\n    time.hour = null;\n    time.minute = null;\n    time.second = null;\n\n    this.icaltype = icaltype || \"date-and-or-time\";\n\n    this.fromData(data, zone);\n  };\n\n  ICAL.VCardTime.prototype = {\n    __proto__: ICAL.Time.prototype,\n\n    icalclass: \"vcardtime\",\n    icaltype: \"date-and-or-time\",\n\n    /**\n     * The timezone. This can either be floating, UTC, or an instance of\n     * ICAL.UtcOffset.\n     */\n    zone: null,\n\n    clone: function() {\n      return new ICAL.VCardTime(this._time, this.zone, this.icaltype);\n    },\n\n    _normalize: function() {\n      return this;\n    },\n\n    utcOffset: function() {\n      if (this.zone instanceof ICAL.UtcOffset) {\n        return this.zone.toSeconds();\n      } else {\n        return ICAL.Time.prototype.utcOffset.apply(this, arguments);\n      }\n    },\n\n    toICALString: function() {\n      return ICAL.design.vcard.value[this.icaltype].toICAL(this.toString());\n    },\n\n    toString: function toString() {\n      var p2 = ICAL.helpers.pad2;\n      var y = this.year, m = this.month, d = this.day;\n      var h = this.hour, mm = this.minute, s = this.second;\n\n      var hasYear = y !== null, hasMonth = m !== null, hasDay = d !== null;\n      var hasHour = h !== null, hasMinute = mm !== null, hasSecond = s !== null;\n\n      var datepart = (hasYear ? p2(y) + (hasMonth || hasDay ? '-' : '') : (hasMonth || hasDay ? '--' : '')) +\n                     (hasMonth ? p2(m) : '') +\n                     (hasDay ? '-' + p2(d) : '');\n      var timepart = (hasHour ? p2(h) : '-') + (hasHour && hasMinute ? ':' : '') +\n                     (hasMinute ? p2(mm) : '') + (!hasHour && !hasMinute ? '-' : '') +\n                     (hasMinute && hasSecond ? ':' : '') +\n                     (hasSecond ? p2(s) : '');\n\n      var zone;\n      if (this.zone === ICAL.Timezone.utcTimezone) {\n        zone = 'Z';\n      } else if (this.zone instanceof ICAL.UtcOffset) {\n        zone = this.zone.toString();\n      } else if (this.zone === ICAL.Timezone.localTimezone) {\n        zone = '';\n      } else if (this.zone instanceof ICAL.Timezone) {\n        var offset = ICAL.UtcOffset.fromSeconds(this.zone.utcOffset(this));\n        zone = offset.toString();\n      } else {\n        zone = '';\n      }\n\n      switch (this.icaltype) {\n        case \"time\":\n          return timepart + zone;\n        case \"date-and-or-time\":\n        case \"date-time\":\n          return datepart + (timepart == '--' ? '' : 'T' + timepart + zone);\n        case \"date\":\n          return datepart;\n      }\n      return null;\n    }\n  };\n\n  ICAL.VCardTime.fromDateAndOrTimeString = function(aValue, aIcalType) {\n    function part(v, s, e) {\n      return v ? ICAL.helpers.strictParseInt(v.substr(s, e)) : null;\n    }\n    var parts = aValue.split('T');\n    var dt = parts[0], tmz = parts[1];\n    var splitzone = tmz ? ICAL.design.vcard.value.time._splitZone(tmz) : [];\n    var zone = splitzone[0], tm = splitzone[1];\n\n    var stoi = ICAL.helpers.strictParseInt;\n    var dtlen = dt ? dt.length : 0;\n    var tmlen = tm ? tm.length : 0;\n\n    var hasDashDate = dt && dt[0] == '-' && dt[1] == '-';\n    var hasDashTime = tm && tm[0] == '-';\n\n    var o = {\n      year: hasDashDate ? null : part(dt, 0, 4),\n      month: hasDashDate && (dtlen == 4 || dtlen == 7) ? part(dt, 2, 2) : dtlen == 7 ? part(dt, 5, 2) : dtlen == 10 ? part(dt, 5, 2) : null,\n      day: dtlen == 5 ? part(dt, 3, 2) : dtlen == 7 && hasDashDate ? part(dt, 5, 2) : dtlen == 10 ? part(dt, 8, 2) : null,\n\n      hour: hasDashTime ? null : part(tm, 0, 2),\n      minute: hasDashTime && tmlen == 3 ? part(tm, 1, 2) : tmlen > 4 ? hasDashTime ? part(tm, 1, 2) : part(tm, 3, 2) : null,\n      second: tmlen == 4 ? part(tm, 2, 2) : tmlen == 6 ? part(tm, 4, 2) : tmlen == 8 ? part(tm, 6, 2) : null\n    };\n\n    if (zone == 'Z') {\n      zone = ICAL.Timezone.utcTimezone;\n    } else if (zone && zone[3] == ':') {\n      zone = ICAL.UtcOffset.fromString(zone);\n    } else {\n      zone = null;\n    }\n\n    return new ICAL.VCardTime(o, zone, aIcalType);\n  };\n})();\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n * Portions Copyright (C) Philipp Kewisch, 2011-2012 */\n\n\n\n/* istanbul ignore next */\n(typeof(ICAL) === 'undefined') ? ICAL = {} : ''; // jshint ignore:line\n\n(function() {\n\n  var DOW_MAP = {\n    SU: ICAL.Time.SUNDAY,\n    MO: ICAL.Time.MONDAY,\n    TU: ICAL.Time.TUESDAY,\n    WE: ICAL.Time.WEDNESDAY,\n    TH: ICAL.Time.THURSDAY,\n    FR: ICAL.Time.FRIDAY,\n    SA: ICAL.Time.SATURDAY\n  };\n\n  var REVERSE_DOW_MAP = {};\n  for (var key in DOW_MAP) {\n    REVERSE_DOW_MAP[DOW_MAP[key]] = key;\n  }\n\n  var COPY_PARTS = [\"BYSECOND\", \"BYMINUTE\", \"BYHOUR\", \"BYDAY\",\n                    \"BYMONTHDAY\", \"BYYEARDAY\", \"BYWEEKNO\",\n                    \"BYMONTH\", \"BYSETPOS\"];\n\n  ICAL.Recur = function icalrecur(data) {\n    this.wrappedJSObject = this;\n    this.parts = {};\n\n    if (data && typeof(data) === 'object') {\n      this.fromData(data);\n    }\n  };\n\n  ICAL.Recur.prototype = {\n\n    parts: null,\n\n    interval: 1,\n    wkst: ICAL.Time.MONDAY,\n    until: null,\n    count: null,\n    freq: null,\n    icalclass: \"icalrecur\",\n    icaltype: \"recur\",\n\n    iterator: function(aStart) {\n      return new ICAL.RecurIterator({\n        rule: this,\n        dtstart: aStart\n      });\n    },\n\n    clone: function clone() {\n      return new ICAL.Recur(this.toJSON());\n    },\n\n    isFinite: function isfinite() {\n      return !!(this.count || this.until);\n    },\n\n    isByCount: function isbycount() {\n      return !!(this.count && !this.until);\n    },\n\n    addComponent: function addPart(aType, aValue) {\n      var ucname = aType.toUpperCase();\n      if (ucname in this.parts) {\n        this.parts[ucname].push(aValue);\n      } else {\n        this.parts[ucname] = [aValue];\n      }\n    },\n\n    setComponent: function setComponent(aType, aValues) {\n      this.parts[aType.toUpperCase()] = aValues.slice();\n    },\n\n    getComponent: function getComponent(aType) {\n      var ucname = aType.toUpperCase();\n      return (ucname in this.parts ? this.parts[ucname].slice() : []);\n    },\n\n    getNextOccurrence: function getNextOccurrence(aStartTime, aRecurrenceId) {\n      var iter = this.iterator(aStartTime);\n      var next, cdt;\n\n      do {\n        next = iter.next();\n      } while (next && next.compare(aRecurrenceId) <= 0);\n\n      if (next && aRecurrenceId.zone) {\n        next.zone = aRecurrenceId.zone;\n      }\n\n      return next;\n    },\n\n    fromData: function(data) {\n      for (var key in data) {\n        var uckey = key.toUpperCase();\n\n        if (uckey in partDesign) {\n          if (Array.isArray(data[key])) {\n            this.parts[uckey] = data[key];\n          } else {\n            this.parts[uckey] = [data[key]];\n          }\n        } else {\n          this[key] = data[key];\n        }\n      }\n\n      if (this.wkst && typeof this.wkst != \"number\") {\n        this.wkst = ICAL.Recur.icalDayToNumericDay(this.wkst);\n      }\n\n      if (this.until && !(this.until instanceof ICAL.Time)) {\n        this.until = ICAL.Time.fromString(this.until);\n      }\n    },\n\n    toJSON: function() {\n      var res = Object.create(null);\n      res.freq = this.freq;\n\n      if (this.count) {\n        res.count = this.count;\n      }\n\n      if (this.interval > 1) {\n        res.interval = this.interval;\n      }\n\n      for (var k in this.parts) {\n        var kparts = this.parts[k];\n        if (Array.isArray(kparts) && kparts.length == 1) {\n          res[k.toLowerCase()] = kparts[0];\n        } else {\n          res[k.toLowerCase()] = ICAL.helpers.clone(this.parts[k]);\n        }\n      }\n\n      if (this.until) {\n        res.until = this.until.toString();\n      }\n      if ('wkst' in this && this.wkst !== ICAL.Time.DEFAULT_WEEK_START) {\n        res.wkst = ICAL.Recur.numericDayToIcalDay(this.wkst);\n      }\n      return res;\n    },\n\n    toString: function icalrecur_toString() {\n      // TODO retain order\n      var str = \"FREQ=\" + this.freq;\n      if (this.count) {\n        str += \";COUNT=\" + this.count;\n      }\n      if (this.interval > 1) {\n        str += \";INTERVAL=\" + this.interval;\n      }\n      for (var k in this.parts) {\n        str += \";\" + k + \"=\" + this.parts[k];\n      }\n      if (this.until) {\n        str += ';UNTIL=' + this.until.toString();\n      }\n      if ('wkst' in this && this.wkst !== ICAL.Time.DEFAULT_WEEK_START) {\n        str += ';WKST=' + ICAL.Recur.numericDayToIcalDay(this.wkst);\n      }\n      return str;\n    }\n  };\n\n  function parseNumericValue(type, min, max, value) {\n    var result = value;\n\n    if (value[0] === '+') {\n      result = value.substr(1);\n    }\n\n    result = ICAL.helpers.strictParseInt(result);\n\n    if (min !== undefined && value < min) {\n      throw new Error(\n        type + ': invalid value \"' + value + '\" must be > ' + min\n      );\n    }\n\n    if (max !== undefined && value > max) {\n      throw new Error(\n        type + ': invalid value \"' + value + '\" must be < ' + min\n      );\n    }\n\n    return result;\n  }\n\n  /**\n   * Convert an ical representation of a day (SU, MO, etc..)\n   * into a numeric value of that day.\n   *\n   * @param {String} day ical day.\n   * @return {Numeric} numeric value of given day.\n   */\n  ICAL.Recur.icalDayToNumericDay = function toNumericDay(string) {\n    //XXX: this is here so we can deal\n    //     with possibly invalid string values.\n\n    return DOW_MAP[string];\n  };\n\n  /**\n   * Convert a numeric day value into its ical representation (SU, MO, etc..)\n   *\n   * @param {Numeric} numeric value of given day.\n   * @return {String} day ical day.\n   */\n  ICAL.Recur.numericDayToIcalDay = function toIcalDay(num) {\n    //XXX: this is here so we can deal with possibly invalid number values.\n    //     Also, this allows consistent mapping between day numbers and day\n    //     names for external users.\n    return REVERSE_DOW_MAP[num];\n  };\n\n  var VALID_DAY_NAMES = /^(SU|MO|TU|WE|TH|FR|SA)$/;\n  var VALID_BYDAY_PART = /^([+-])?(5[0-3]|[1-4][0-9]|[1-9])?(SU|MO|TU|WE|TH|FR|SA)$/;\n  var ALLOWED_FREQ = ['SECONDLY', 'MINUTELY', 'HOURLY',\n                      'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY'];\n\n  var optionDesign = {\n    FREQ: function(value, dict, fmtIcal) {\n      // yes this is actually equal or faster then regex.\n      // upside here is we can enumerate the valid values.\n      if (ALLOWED_FREQ.indexOf(value) !== -1) {\n        dict.freq = value;\n      } else {\n        throw new Error(\n          'invalid frequency \"' + value + '\" expected: \"' +\n          ALLOWED_FREQ.join(', ') + '\"'\n        );\n      }\n    },\n\n    COUNT: function(value, dict, fmtIcal) {\n      dict.count = ICAL.helpers.strictParseInt(value);\n    },\n\n    INTERVAL: function(value, dict, fmtIcal) {\n      dict.interval = ICAL.helpers.strictParseInt(value);\n      if (dict.interval < 1) {\n        // 0 or negative values are not allowed, some engines seem to generate\n        // it though. Assume 1 instead.\n        dict.interval = 1;\n      }\n    },\n\n    UNTIL: function(value, dict, fmtIcal) {\n      if (fmtIcal) {\n        if (value.length > 10) {\n          dict.until = ICAL.design.icalendar.value['date-time'].fromICAL(value);\n        } else {\n          dict.until = ICAL.design.icalendar.value.date.fromICAL(value);\n        }\n      } else {\n        dict.until = ICAL.Time.fromString(value);\n      }\n    },\n\n    WKST: function(value, dict, fmtIcal) {\n      if (VALID_DAY_NAMES.test(value)) {\n        dict.wkst = ICAL.Recur.icalDayToNumericDay(value);\n      } else {\n        throw new Error('invalid WKST value \"' + value + '\"');\n      }\n    }\n  };\n\n  var partDesign = {\n    BYSECOND: parseNumericValue.bind(this, 'BYSECOND', 0, 60),\n    BYMINUTE: parseNumericValue.bind(this, 'BYMINUTE', 0, 59),\n    BYHOUR: parseNumericValue.bind(this, 'BYHOUR', 0, 23),\n    BYDAY: function(value) {\n      if (VALID_BYDAY_PART.test(value)) {\n        return value;\n      } else {\n        throw new Error('invalid BYDAY value \"' + value + '\"');\n      }\n    },\n    BYMONTHDAY: parseNumericValue.bind(this, 'BYMONTHDAY', -31, 31),\n    BYYEARDAY: parseNumericValue.bind(this, 'BYYEARDAY', -366, 366),\n    BYWEEKNO: parseNumericValue.bind(this, 'BYWEEKNO', -53, 53),\n    BYMONTH: parseNumericValue.bind(this, 'BYMONTH', 0, 12),\n    BYSETPOS: parseNumericValue.bind(this, 'BYSETPOS', -366, 366)\n  };\n\n  ICAL.Recur.fromString = function(string) {\n    var data = ICAL.Recur._stringToData(string, false);\n    return new ICAL.Recur(data);\n  };\n\n  ICAL.Recur.fromData = function(aData) {\n    return new ICAL.Recur(aData);\n  };\n\n  ICAL.Recur._stringToData = function(string, fmtIcal) {\n    var dict = Object.create(null);\n\n    // split is slower in FF but fast enough.\n    // v8 however this is faster then manual split?\n    var values = string.split(';');\n    var len = values.length;\n\n    for (var i = 0; i < len; i++) {\n      var parts = values[i].split('=');\n      var ucname = parts[0].toUpperCase();\n      var lcname = parts[0].toLowerCase();\n      var name = (fmtIcal ? lcname : ucname);\n      var value = parts[1];\n\n      if (ucname in partDesign) {\n        var partArr = value.split(',');\n        var partArrIdx = 0;\n        var partArrLen = partArr.length;\n\n        for (; partArrIdx < partArrLen; partArrIdx++) {\n          partArr[partArrIdx] = partDesign[ucname](partArr[partArrIdx]);\n        }\n        dict[name] = (partArr.length == 1 ? partArr[0] : partArr);\n      } else if (ucname in optionDesign) {\n        optionDesign[ucname](value, dict, fmtIcal);\n      } else {\n        // Don't swallow unknown values. Just set them as they are.\n        dict[lcname] = value;\n      }\n    }\n\n    return dict;\n  };\n\n})();\nICAL.RecurIterator = (function() {\n\n  /**\n   * Options:\n   *  - rule: (ICAL.Recur) instance\n   *  - dtstart: (ICAL.Time) start date of recurrence rule\n   *  - initialized: (Boolean) when true will assume options\n   *                           are from previously constructed\n   *                           iterator and will not re-initialize\n   *                           iterator but resume its state from given data.\n   *\n   *  - by_data: (for iterator de-serialization)\n   *  - days: \"\n   *  - last: \"\n   *  - by_indices: \"\n   */\n  function icalrecur_iterator(options) {\n    this.fromData(options);\n  }\n\n  icalrecur_iterator.prototype = {\n\n    /**\n     * True when iteration is finished.\n     */\n    completed: false,\n\n    rule: null,\n    dtstart: null,\n    last: null,\n    occurrence_number: 0,\n    by_indices: null,\n    initialized: false,\n    by_data: null,\n\n    days: null,\n    days_index: 0,\n\n    fromData: function(options) {\n      this.rule = ICAL.helpers.formatClassType(options.rule, ICAL.Recur);\n\n      if (!this.rule) {\n        throw new Error('iterator requires a (ICAL.Recur) rule');\n      }\n\n      this.dtstart = ICAL.helpers.formatClassType(options.dtstart, ICAL.Time);\n\n      if (!this.dtstart) {\n        throw new Error('iterator requires a (ICAL.Time) dtstart');\n      }\n\n      if (options.by_data) {\n        this.by_data = options.by_data;\n      } else {\n        this.by_data = ICAL.helpers.clone(this.rule.parts, true);\n      }\n\n      if (options.occurrence_number)\n        this.occurrence_number = options.occurrence_number;\n\n      this.days = options.days || [];\n      this.last = ICAL.helpers.formatClassType(options.last, ICAL.Time);\n\n      this.by_indices = options.by_indices;\n\n      if (!this.by_indices) {\n        this.by_indices = {\n          \"BYSECOND\": 0,\n          \"BYMINUTE\": 0,\n          \"BYHOUR\": 0,\n          \"BYDAY\": 0,\n          \"BYMONTH\": 0,\n          \"BYWEEKNO\": 0,\n          \"BYMONTHDAY\": 0\n        };\n      }\n\n      this.initialized = options.initialized || false;\n\n      if (!this.initialized) {\n        this.init();\n      }\n    },\n\n    init: function icalrecur_iterator_init() {\n      this.initialized = true;\n      this.last = this.dtstart.clone();\n      var parts = this.by_data;\n\n      if (\"BYDAY\" in parts) {\n        // libical does this earlier when the rule is loaded, but we postpone to\n        // now so we can preserve the original order.\n        this.sort_byday_rules(parts.BYDAY, this.rule.wkst);\n      }\n\n      // If the BYYEARDAY appares, no other date rule part may appear\n      if (\"BYYEARDAY\" in parts) {\n        if (\"BYMONTH\" in parts || \"BYWEEKNO\" in parts ||\n            \"BYMONTHDAY\" in parts || \"BYDAY\" in parts) {\n          throw new Error(\"Invalid BYYEARDAY rule\");\n        }\n      }\n\n      // BYWEEKNO and BYMONTHDAY rule parts may not both appear\n      if (\"BYWEEKNO\" in parts && \"BYMONTHDAY\" in parts) {\n        throw new Error(\"BYWEEKNO does not fit to BYMONTHDAY\");\n      }\n\n      // For MONTHLY recurrences (FREQ=MONTHLY) neither BYYEARDAY nor\n      // BYWEEKNO may appear.\n      if (this.rule.freq == \"MONTHLY\" &&\n          (\"BYYEARDAY\" in parts || \"BYWEEKNO\" in parts)) {\n        throw new Error(\"For MONTHLY recurrences neither BYYEARDAY nor BYWEEKNO may appear\");\n      }\n\n      // For WEEKLY recurrences (FREQ=WEEKLY) neither BYMONTHDAY nor\n      // BYYEARDAY may appear.\n      if (this.rule.freq == \"WEEKLY\" &&\n          (\"BYYEARDAY\" in parts || \"BYMONTHDAY\" in parts)) {\n        throw new Error(\"For WEEKLY recurrences neither BYMONTHDAY nor BYYEARDAY may appear\");\n      }\n\n      // BYYEARDAY may only appear in YEARLY rules\n      if (this.rule.freq != \"YEARLY\" && \"BYYEARDAY\" in parts) {\n        throw new Error(\"BYYEARDAY may only appear in YEARLY rules\");\n      }\n\n      this.last.second = this.setup_defaults(\"BYSECOND\", \"SECONDLY\", this.dtstart.second);\n      this.last.minute = this.setup_defaults(\"BYMINUTE\", \"MINUTELY\", this.dtstart.minute);\n      this.last.hour = this.setup_defaults(\"BYHOUR\", \"HOURLY\", this.dtstart.hour);\n      this.last.day = this.setup_defaults(\"BYMONTHDAY\", \"DAILY\", this.dtstart.day);\n      this.last.month = this.setup_defaults(\"BYMONTH\", \"MONTHLY\", this.dtstart.month);\n\n      if (this.rule.freq == \"WEEKLY\") {\n        if (\"BYDAY\" in parts) {\n          var bydayParts = this.ruleDayOfWeek(parts.BYDAY[0]);\n          var pos = bydayParts[0];\n          var dow = bydayParts[1];\n          var wkdy = dow - this.last.dayOfWeek();\n          if ((this.last.dayOfWeek() < dow && wkdy >= 0) || wkdy < 0) {\n            // Initial time is after first day of BYDAY data\n            this.last.day += wkdy;\n          }\n        } else {\n          var dayName = ICAL.Recur.numericDayToIcalDay(this.dtstart.dayOfWeek());\n          parts.BYDAY = [dayName];\n        }\n      }\n\n      if (this.rule.freq == \"YEARLY\") {\n        for (;;) {\n          this.expand_year_days(this.last.year);\n          if (this.days.length > 0) {\n            break;\n          }\n          this.increment_year(this.rule.interval);\n        }\n\n        var next = ICAL.Time.fromDayOfYear(this.days[0], this.last.year);\n\n        this.last.day = next.day;\n        this.last.month = next.month;\n      }\n\n      if (this.rule.freq == \"MONTHLY\" && this.has_by_data(\"BYDAY\")) {\n        var tempLast = null;\n        var initLast = this.last.clone();\n        var daysInMonth = ICAL.Time.daysInMonth(this.last.month, this.last.year);\n\n        // Check every weekday in BYDAY with relative dow and pos.\n        for (var i in this.by_data.BYDAY) {\n          this.last = initLast.clone();\n          var bydayParts = this.ruleDayOfWeek(this.by_data.BYDAY[i]);\n          var pos = bydayParts[0];\n          var dow = bydayParts[1];\n          var dayOfMonth = this.last.nthWeekDay(dow, pos);\n\n          // If |pos| >= 6, the byday is invalid for a monthly rule.\n          if (pos >= 6 || pos <= -6) {\n            throw new Error(\"Malformed values in BYDAY part\");\n          }\n\n          // If a Byday with pos=+/-5 is not in the current month it\n          // must be searched in the next months.\n          if (dayOfMonth > daysInMonth || dayOfMonth <= 0) {\n            // Skip if we have already found a \"last\" in this month.\n            if (tempLast && tempLast.month == initLast.month) {\n              continue;\n            }\n            while (dayOfMonth > daysInMonth || dayOfMonth <= 0) {\n              this.increment_month();\n              daysInMonth = ICAL.Time.daysInMonth(this.last.month, this.last.year);\n              dayOfMonth = this.last.nthWeekDay(dow, pos);\n            }\n          }\n\n          this.last.day = dayOfMonth;\n          if (!tempLast || this.last.compare(tempLast) < 0) {\n            tempLast = this.last.clone();\n          }\n        }\n        this.last = tempLast.clone();\n\n        //XXX: This feels like a hack, but we need to initialize\n        //     the BYMONTHDAY case correctly and byDayAndMonthDay handles\n        //     this case. It accepts a special flag which will avoid incrementing\n        //     the initial value without the flag days that match the start time\n        //     would be missed.\n        if (this.has_by_data('BYMONTHDAY')) {\n          this._byDayAndMonthDay(true);\n        }\n\n        if (this.last.day > daysInMonth || this.last.day == 0) {\n          throw new Error(\"Malformed values in BYDAY part\");\n        }\n\n      } else if (this.has_by_data(\"BYMONTHDAY\")) {\n        if (this.last.day < 0) {\n          var daysInMonth = ICAL.Time.daysInMonth(this.last.month, this.last.year);\n          this.last.day = daysInMonth + this.last.day + 1;\n        }\n      }\n\n    },\n\n    next: function icalrecur_iterator_next() {\n      var before = (this.last ? this.last.clone() : null);\n\n      if ((this.rule.count && this.occurrence_number >= this.rule.count) ||\n          (this.rule.until && this.last.compare(this.rule.until) > 0)) {\n\n        //XXX: right now this is just a flag and has no impact\n        //     we can simplify the above case to check for completed later.\n        this.completed = true;\n\n        return null;\n      }\n\n      if (this.occurrence_number == 0 && this.last.compare(this.dtstart) >= 0) {\n        // First of all, give the instance that was initialized\n        this.occurrence_number++;\n        return this.last;\n      }\n\n\n      var valid;\n      do {\n        valid = 1;\n\n        switch (this.rule.freq) {\n        case \"SECONDLY\":\n          this.next_second();\n          break;\n        case \"MINUTELY\":\n          this.next_minute();\n          break;\n        case \"HOURLY\":\n          this.next_hour();\n          break;\n        case \"DAILY\":\n          this.next_day();\n          break;\n        case \"WEEKLY\":\n          this.next_week();\n          break;\n        case \"MONTHLY\":\n          valid = this.next_month();\n          break;\n        case \"YEARLY\":\n          this.next_year();\n          break;\n\n        default:\n          return null;\n        }\n      } while (!this.check_contracting_rules() ||\n               this.last.compare(this.dtstart) < 0 ||\n               !valid);\n\n      // TODO is this valid?\n      if (this.last.compare(before) == 0) {\n        throw new Error(\"Same occurrence found twice, protecting \" +\n                        \"you from death by recursion\");\n      }\n\n      if (this.rule.until && this.last.compare(this.rule.until) > 0) {\n        this.completed = true;\n        return null;\n      } else {\n        this.occurrence_number++;\n        return this.last;\n      }\n    },\n\n    next_second: function next_second() {\n      return this.next_generic(\"BYSECOND\", \"SECONDLY\", \"second\", \"minute\");\n    },\n\n    increment_second: function increment_second(inc) {\n      return this.increment_generic(inc, \"second\", 60, \"minute\");\n    },\n\n    next_minute: function next_minute() {\n      return this.next_generic(\"BYMINUTE\", \"MINUTELY\",\n                               \"minute\", \"hour\", \"next_second\");\n    },\n\n    increment_minute: function increment_minute(inc) {\n      return this.increment_generic(inc, \"minute\", 60, \"hour\");\n    },\n\n    next_hour: function next_hour() {\n      return this.next_generic(\"BYHOUR\", \"HOURLY\", \"hour\",\n                               \"monthday\", \"next_minute\");\n    },\n\n    increment_hour: function increment_hour(inc) {\n      this.increment_generic(inc, \"hour\", 24, \"monthday\");\n    },\n\n    next_day: function next_day() {\n      var has_by_day = (\"BYDAY\" in this.by_data);\n      var this_freq = (this.rule.freq == \"DAILY\");\n\n      if (this.next_hour() == 0) {\n        return 0;\n      }\n\n      if (this_freq) {\n        this.increment_monthday(this.rule.interval);\n      } else {\n        this.increment_monthday(1);\n      }\n\n      return 0;\n    },\n\n    next_week: function next_week() {\n      var end_of_data = 0;\n\n      if (this.next_weekday_by_week() == 0) {\n        return end_of_data;\n      }\n\n      if (this.has_by_data(\"BYWEEKNO\")) {\n        var idx = ++this.by_indices.BYWEEKNO;\n\n        if (this.by_indices.BYWEEKNO == this.by_data.BYWEEKNO.length) {\n          this.by_indices.BYWEEKNO = 0;\n          end_of_data = 1;\n        }\n\n        // HACK should be first month of the year\n        this.last.month = 1;\n        this.last.day = 1;\n\n        var week_no = this.by_data.BYWEEKNO[this.by_indices.BYWEEKNO];\n\n        this.last.day += 7 * week_no;\n\n        if (end_of_data) {\n          this.increment_year(1);\n        }\n      } else {\n        // Jump to the next week\n        this.increment_monthday(7 * this.rule.interval);\n      }\n\n      return end_of_data;\n    },\n\n    /**\n     * normalize each by day rule for a given year/month.\n     * Takes into account ordering and negative rules\n     *\n     * @param {Numeric} year current year.\n     * @param {Numeric} month current month.\n     * @param {Array} rules array of rules.\n     *\n     * @return {Array} sorted and normalized rules.\n     *                 Negative rules will be expanded to their\n     *                 correct positive values for easier processing.\n     */\n    normalizeByMonthDayRules: function(year, month, rules) {\n      var daysInMonth = ICAL.Time.daysInMonth(month, year);\n\n      // XXX: This is probably bad for performance to allocate\n      //      a new array for each month we scan, if possible\n      //      we should try to optimize this...\n      var newRules = [];\n\n      var ruleIdx = 0;\n      var len = rules.length;\n      var rule;\n\n      for (; ruleIdx < len; ruleIdx++) {\n        rule = rules[ruleIdx];\n\n        // if this rule falls outside of given\n        // month discard it.\n        if (Math.abs(rule) > daysInMonth) {\n          continue;\n        }\n\n        // negative case\n        if (rule < 0) {\n          // we add (not subtract its a negative number)\n          // one from the rule because 1 === last day of month\n          rule = daysInMonth + (rule + 1);\n        } else if (rule === 0) {\n          // skip zero its invalid.\n          continue;\n        }\n\n        // only add unique items...\n        if (newRules.indexOf(rule) === -1) {\n          newRules.push(rule);\n        }\n\n      }\n\n      // unique and sort\n      return newRules.sort(function(a, b) { return a - b; });\n    },\n\n    /**\n     * NOTES:\n     * We are given a list of dates in the month (BYMONTHDAY) (23, etc..)\n     * Also we are given a list of days (BYDAY) (MO, 2SU, etc..) when\n     * both conditions match a given date (this.last.day) iteration stops.\n     *\n     * @param {Boolean} [isInit] when given true will not\n     *                           increment the current day (this.last).\n     */\n    _byDayAndMonthDay: function(isInit) {\n      var byMonthDay; // setup in initMonth\n      var byDay = this.by_data.BYDAY;\n\n      var date;\n      var dateIdx = 0;\n      var dateLen; // setup in initMonth\n      var dayLen = byDay.length;\n\n      // we are not valid by default\n      var dataIsValid = 0;\n\n      var daysInMonth;\n      var self = this;\n      // we need a copy of this, because a DateTime gets normalized\n      // automatically if the day is out of range. At some points we\n      // set the last day to 0 to start counting.\n      var lastDay = this.last.day;\n\n      function initMonth() {\n        daysInMonth = ICAL.Time.daysInMonth(\n          self.last.month, self.last.year\n        );\n\n        byMonthDay = self.normalizeByMonthDayRules(\n          self.last.year,\n          self.last.month,\n          self.by_data.BYMONTHDAY\n        );\n\n        dateLen = byMonthDay.length;\n\n        // For the case of more than one occurrence in one month\n        // we have to be sure to start searching after the last\n        // found date or at the last BYMONTHDAY.\n        while (byMonthDay[dateIdx] <= lastDay && dateIdx < dateLen - 1) {\n          dateIdx++;\n        }\n      }\n\n      function nextMonth() {\n        // since the day is incremented at the start\n        // of the loop below, we need to start at 0\n        lastDay = 0;\n        self.increment_month();\n        dateIdx = 0;\n        initMonth();\n      }\n\n      initMonth();\n\n      // should come after initMonth\n      if (isInit) {\n        lastDay -= 1;\n      }\n\n      while (!dataIsValid) {\n        // increment the current date. This is really\n        // important otherwise we may fall into the infinite\n        // loop trap. The initial date takes care of the case\n        // where the current date is the date we are looking\n        // for.\n        date = lastDay + 1;\n\n        if (date > daysInMonth) {\n          nextMonth();\n          continue;\n        }\n\n        // find next date\n        var next = byMonthDay[dateIdx++];\n\n        // this logic is dependant on the BYMONTHDAYS\n        // being in order (which is done by #normalizeByMonthDayRules)\n        if (next >= date) {\n          // if the next month day is in the future jump to it.\n          lastDay = next;\n        } else {\n          // in this case the 'next' monthday has past\n          // we must move to the month.\n          nextMonth();\n          continue;\n        }\n\n        // Now we can loop through the day rules to see\n        // if one matches the current month date.\n        for (var dayIdx = 0; dayIdx < dayLen; dayIdx++) {\n          var parts = this.ruleDayOfWeek(byDay[dayIdx]);\n          var pos = parts[0];\n          var dow = parts[1];\n\n          this.last.day = lastDay;\n          if (this.last.isNthWeekDay(dow, pos)) {\n            // when we find the valid one we can mark\n            // the conditions as met and break the loop.\n            // (Because we have this condition above\n            //  it will also break the parent loop).\n            dataIsValid = 1;\n            break;\n          }\n        }\n\n        // Its completely possible that the combination\n        // cannot be matched in the current month.\n        // When we reach the end of possible combinations\n        // in the current month we iterate to the next one.\n        // since dateIdx is incremented right after getting\n        // \"next\", we don't need dateLen -1 here.\n        if (!dataIsValid && dateIdx === dateLen) {\n          nextMonth();\n          continue;\n        }\n      }\n\n      return dataIsValid;\n    },\n\n    next_month: function next_month() {\n      var this_freq = (this.rule.freq == \"MONTHLY\");\n      var data_valid = 1;\n\n      if (this.next_hour() == 0) {\n        return data_valid;\n      }\n\n      if (this.has_by_data(\"BYDAY\") && this.has_by_data(\"BYMONTHDAY\")) {\n        data_valid = this._byDayAndMonthDay();\n      } else if (this.has_by_data(\"BYDAY\")) {\n        var daysInMonth = ICAL.Time.daysInMonth(this.last.month, this.last.year);\n        var setpos = 0;\n        var setpos_total = 0;\n\n        if (this.has_by_data(\"BYSETPOS\")) {\n          var last_day = this.last.day;\n          for (var day = 1; day <= daysInMonth; day++) {\n            this.last.day = day;\n            if (this.is_day_in_byday(this.last)) {\n              setpos_total++;\n              if (day <= last_day) {\n                setpos++;\n              }\n            }\n          }\n          this.last.day = last_day;\n        }\n\n        data_valid = 0;\n        for (var day = this.last.day + 1; day <= daysInMonth; day++) {\n          this.last.day = day;\n\n          if (this.is_day_in_byday(this.last)) {\n            if (!this.has_by_data(\"BYSETPOS\") ||\n                this.check_set_position(++setpos) ||\n                this.check_set_position(setpos - setpos_total - 1)) {\n\n              data_valid = 1;\n              break;\n            }\n          }\n        }\n\n        if (day > daysInMonth) {\n          this.last.day = 1;\n          this.increment_month();\n\n          if (this.is_day_in_byday(this.last)) {\n            if (!this.has_by_data(\"BYSETPOS\") || this.check_set_position(1)) {\n              data_valid = 1;\n            }\n          } else {\n            data_valid = 0;\n          }\n        }\n      } else if (this.has_by_data(\"BYMONTHDAY\")) {\n        this.by_indices.BYMONTHDAY++;\n\n        if (this.by_indices.BYMONTHDAY >= this.by_data.BYMONTHDAY.length) {\n          this.by_indices.BYMONTHDAY = 0;\n          this.increment_month();\n        }\n\n        var daysInMonth = ICAL.Time.daysInMonth(this.last.month, this.last.year);\n        var day = this.by_data.BYMONTHDAY[this.by_indices.BYMONTHDAY];\n\n        if (day < 0) {\n          day = daysInMonth + day + 1;\n        }\n\n        if (day > daysInMonth) {\n          this.last.day = 1;\n          data_valid = this.is_day_in_byday(this.last);\n        } else {\n          this.last.day = day;\n        }\n\n      } else {\n        this.increment_month();\n        var daysInMonth = ICAL.Time.daysInMonth(this.last.month, this.last.year);\n        if (this.by_data.BYMONTHDAY[0] > daysInMonth) {\n          data_valid = 0;\n        } else {\n          this.last.day = this.by_data.BYMONTHDAY[0];\n        }\n      }\n\n      return data_valid;\n    },\n\n    next_weekday_by_week: function next_weekday_by_week() {\n      var end_of_data = 0;\n\n      if (this.next_hour() == 0) {\n        return end_of_data;\n      }\n\n      if (!this.has_by_data(\"BYDAY\")) {\n        return 1;\n      }\n\n      for (;;) {\n        var tt = new ICAL.Time();\n        this.by_indices.BYDAY++;\n\n        if (this.by_indices.BYDAY == Object.keys(this.by_data.BYDAY).length) {\n          this.by_indices.BYDAY = 0;\n          end_of_data = 1;\n        }\n\n        var coded_day = this.by_data.BYDAY[this.by_indices.BYDAY];\n        var parts = this.ruleDayOfWeek(coded_day);\n        var dow = parts[1];\n\n        dow -= this.rule.wkst;\n\n        if (dow < 0) {\n          dow += 7;\n        }\n\n        tt.year = this.last.year;\n        tt.month = this.last.month;\n        tt.day = this.last.day;\n\n        var startOfWeek = tt.startDoyWeek(this.rule.wkst);\n\n        if (dow + startOfWeek < 1) {\n          // The selected date is in the previous year\n          if (!end_of_data) {\n            continue;\n          }\n        }\n\n        var next = ICAL.Time.fromDayOfYear(startOfWeek + dow,\n                                                  this.last.year);\n\n        /**\n         * The normalization horrors below are due to\n         * the fact that when the year/month/day changes\n         * it can effect the other operations that come after.\n         */\n        this.last.year = next.year;\n        this.last.month = next.month;\n        this.last.day = next.day;\n\n        return end_of_data;\n      }\n    },\n\n    next_year: function next_year() {\n\n      if (this.next_hour() == 0) {\n        return 0;\n      }\n\n      if (++this.days_index == this.days.length) {\n        this.days_index = 0;\n        do {\n          this.increment_year(this.rule.interval);\n          this.expand_year_days(this.last.year);\n        } while (this.days.length == 0);\n      }\n\n      var next = ICAL.Time.fromDayOfYear(this.days[this.days_index],\n                                                this.last.year);\n\n      this.last.day = next.day;\n      this.last.month = next.month;\n\n      return 1;\n    },\n\n    ruleDayOfWeek: function ruleDayOfWeek(dow) {\n      var matches = dow.match(/([+-]?[0-9])?(MO|TU|WE|TH|FR|SA|SU)/);\n      if (matches) {\n        var pos = parseInt(matches[1] || 0, 10);\n        dow = ICAL.Recur.icalDayToNumericDay(matches[2]);\n        return [pos, dow];\n      } else {\n        return [0, 0];\n      }\n    },\n\n    next_generic: function next_generic(aRuleType, aInterval, aDateAttr,\n                                        aFollowingAttr, aPreviousIncr) {\n      var has_by_rule = (aRuleType in this.by_data);\n      var this_freq = (this.rule.freq == aInterval);\n      var end_of_data = 0;\n\n      if (aPreviousIncr && this[aPreviousIncr]() == 0) {\n        return end_of_data;\n      }\n\n      if (has_by_rule) {\n        this.by_indices[aRuleType]++;\n        var idx = this.by_indices[aRuleType];\n        var dta = this.by_data[aRuleType];\n\n        if (this.by_indices[aRuleType] == dta.length) {\n          this.by_indices[aRuleType] = 0;\n          end_of_data = 1;\n        }\n        this.last[aDateAttr] = dta[this.by_indices[aRuleType]];\n      } else if (this_freq) {\n        this[\"increment_\" + aDateAttr](this.rule.interval);\n      }\n\n      if (has_by_rule && end_of_data && this_freq) {\n        this[\"increment_\" + aFollowingAttr](1);\n      }\n\n      return end_of_data;\n    },\n\n    increment_monthday: function increment_monthday(inc) {\n      for (var i = 0; i < inc; i++) {\n        var daysInMonth = ICAL.Time.daysInMonth(this.last.month, this.last.year);\n        this.last.day++;\n\n        if (this.last.day > daysInMonth) {\n          this.last.day -= daysInMonth;\n          this.increment_month();\n        }\n      }\n    },\n\n    increment_month: function increment_month() {\n      this.last.day = 1;\n      if (this.has_by_data(\"BYMONTH\")) {\n        this.by_indices.BYMONTH++;\n\n        if (this.by_indices.BYMONTH == this.by_data.BYMONTH.length) {\n          this.by_indices.BYMONTH = 0;\n          this.increment_year(1);\n        }\n\n        this.last.month = this.by_data.BYMONTH[this.by_indices.BYMONTH];\n      } else {\n        if (this.rule.freq == \"MONTHLY\") {\n          this.last.month += this.rule.interval;\n        } else {\n          this.last.month++;\n        }\n\n        this.last.month--;\n        var years = ICAL.helpers.trunc(this.last.month / 12);\n        this.last.month %= 12;\n        this.last.month++;\n\n        if (years != 0) {\n          this.increment_year(years);\n        }\n      }\n    },\n\n    increment_year: function increment_year(inc) {\n      this.last.year += inc;\n    },\n\n    increment_generic: function increment_generic(inc, aDateAttr,\n                                                  aFactor, aNextIncrement) {\n      this.last[aDateAttr] += inc;\n      var nextunit = ICAL.helpers.trunc(this.last[aDateAttr] / aFactor);\n      this.last[aDateAttr] %= aFactor;\n      if (nextunit != 0) {\n        this[\"increment_\" + aNextIncrement](nextunit);\n      }\n    },\n\n    has_by_data: function has_by_data(aRuleType) {\n      return (aRuleType in this.rule.parts);\n    },\n\n    expand_year_days: function expand_year_days(aYear) {\n      var t = new ICAL.Time();\n      this.days = [];\n\n      // We need our own copy with a few keys set\n      var parts = {};\n      var rules = [\"BYDAY\", \"BYWEEKNO\", \"BYMONTHDAY\", \"BYMONTH\", \"BYYEARDAY\"];\n      for (var p in rules) {\n        var part = rules[p];\n        if (part in this.rule.parts) {\n          parts[part] = this.rule.parts[part];\n        }\n      }\n\n      if (\"BYMONTH\" in parts && \"BYWEEKNO\" in parts) {\n        var valid = 1;\n        var validWeeks = {};\n        t.year = aYear;\n        t.isDate = true;\n\n        for (var monthIdx = 0; monthIdx < this.by_data.BYMONTH.length; monthIdx++) {\n          var month = this.by_data.BYMONTH[monthIdx];\n          t.month = month;\n          t.day = 1;\n          var first_week = t.weekNumber(this.rule.wkst);\n          t.day = ICAL.Time.daysInMonth(month, aYear);\n          var last_week = t.weekNumber(this.rule.wkst);\n          for (monthIdx = first_week; monthIdx < last_week; monthIdx++) {\n            validWeeks[monthIdx] = 1;\n          }\n        }\n\n        for (var weekIdx = 0; weekIdx < this.by_data.BYWEEKNO.length && valid; weekIdx++) {\n          var weekno = this.by_data.BYWEEKNO[weekIdx];\n          if (weekno < 52) {\n            valid &= validWeeks[weekIdx];\n          } else {\n            valid = 0;\n          }\n        }\n\n        if (valid) {\n          delete parts.BYMONTH;\n        } else {\n          delete parts.BYWEEKNO;\n        }\n      }\n\n      var partCount = Object.keys(parts).length;\n\n      if (partCount == 0) {\n        var t1 = this.dtstart.clone();\n        t1.year = this.last.year;\n        this.days.push(t1.dayOfYear());\n      } else if (partCount == 1 && \"BYMONTH\" in parts) {\n        for (var monthkey in this.by_data.BYMONTH) {\n          var t2 = this.dtstart.clone();\n          t2.year = aYear;\n          t2.month = this.by_data.BYMONTH[monthkey];\n          t2.isDate = true;\n          this.days.push(t2.dayOfYear());\n        }\n      } else if (partCount == 1 && \"BYMONTHDAY\" in parts) {\n        for (var monthdaykey in this.by_data.BYMONTHDAY) {\n          var t3 = this.dtstart.clone();\n          var day_ = this.by_data.BYMONTHDAY[monthdaykey];\n          if (day_ < 0) {\n            var daysInMonth = ICAL.Time.daysInMonth(t3.month, aYear);\n            day_ = day_ + daysInMonth + 1;\n          }\n          t3.day = day_;\n          t3.year = aYear;\n          t3.isDate = true;\n          this.days.push(t3.dayOfYear());\n        }\n      } else if (partCount == 2 &&\n                 \"BYMONTHDAY\" in parts &&\n                 \"BYMONTH\" in parts) {\n        for (var monthkey in this.by_data.BYMONTH) {\n          var month_ = this.by_data.BYMONTH[monthkey];\n          var daysInMonth = ICAL.Time.daysInMonth(month_, aYear);\n          for (var monthdaykey in this.by_data.BYMONTHDAY) {\n            var day_ = this.by_data.BYMONTHDAY[monthdaykey];\n            if (day_ < 0) {\n              day_ = day_ + daysInMonth + 1;\n            }\n            t.day = day_;\n            t.month = month_;\n            t.year = aYear;\n            t.isDate = true;\n\n            this.days.push(t.dayOfYear());\n          }\n        }\n      } else if (partCount == 1 && \"BYWEEKNO\" in parts) {\n        // TODO unimplemented in libical\n      } else if (partCount == 2 &&\n                 \"BYWEEKNO\" in parts &&\n                 \"BYMONTHDAY\" in parts) {\n        // TODO unimplemented in libical\n      } else if (partCount == 1 && \"BYDAY\" in parts) {\n        this.days = this.days.concat(this.expand_by_day(aYear));\n      } else if (partCount == 2 && \"BYDAY\" in parts && \"BYMONTH\" in parts) {\n        for (var monthkey in this.by_data.BYMONTH) {\n          var month = this.by_data.BYMONTH[monthkey];\n          var daysInMonth = ICAL.Time.daysInMonth(month, aYear);\n\n          t.year = aYear;\n          t.month = this.by_data.BYMONTH[monthkey];\n          t.day = 1;\n          t.isDate = true;\n\n          var first_dow = t.dayOfWeek();\n          var doy_offset = t.dayOfYear() - 1;\n\n          t.day = daysInMonth;\n          var last_dow = t.dayOfWeek();\n\n          if (this.has_by_data(\"BYSETPOS\")) {\n            var set_pos_counter = 0;\n            var by_month_day = [];\n            for (var day = 1; day <= daysInMonth; day++) {\n              t.day = day;\n              if (this.is_day_in_byday(t)) {\n                by_month_day.push(day);\n              }\n            }\n\n            for (var spIndex = 0; spIndex < by_month_day.length; spIndex++) {\n              if (this.check_set_position(spIndex + 1) ||\n                  this.check_set_position(spIndex - by_month_day.length)) {\n                this.days.push(doy_offset + by_month_day[spIndex]);\n              }\n            }\n          } else {\n            for (var daycodedkey in this.by_data.BYDAY) {\n              var coded_day = this.by_data.BYDAY[daycodedkey];\n              var bydayParts = this.ruleDayOfWeek(coded_day);\n              var pos = bydayParts[0];\n              var dow = bydayParts[1];\n              var month_day;\n\n              var first_matching_day = ((dow + 7 - first_dow) % 7) + 1;\n              var last_matching_day = daysInMonth - ((last_dow + 7 - dow) % 7);\n\n              if (pos == 0) {\n                for (var day = first_matching_day; day <= daysInMonth; day += 7) {\n                  this.days.push(doy_offset + day);\n                }\n              } else if (pos > 0) {\n                month_day = first_matching_day + (pos - 1) * 7;\n\n                if (month_day <= daysInMonth) {\n                  this.days.push(doy_offset + month_day);\n                }\n              } else {\n                month_day = last_matching_day + (pos + 1) * 7;\n\n                if (month_day > 0) {\n                  this.days.push(doy_offset + month_day);\n                }\n              }\n            }\n          }\n        }\n        // Return dates in order of occurrence (1,2,3,...) instead\n        // of by groups of weekdays (1,8,15,...,2,9,16,...).\n        this.days.sort(function(a, b) { return a - b; }); // Comparator function allows to sort numbers.\n      } else if (partCount == 2 && \"BYDAY\" in parts && \"BYMONTHDAY\" in parts) {\n        var expandedDays = this.expand_by_day(aYear);\n\n        for (var daykey in expandedDays) {\n          var day = expandedDays[daykey];\n          var tt = ICAL.Time.fromDayOfYear(day, aYear);\n          if (this.by_data.BYMONTHDAY.indexOf(tt.day) >= 0) {\n            this.days.push(day);\n          }\n        }\n      } else if (partCount == 3 &&\n                 \"BYDAY\" in parts &&\n                 \"BYMONTHDAY\" in parts &&\n                 \"BYMONTH\" in parts) {\n        var expandedDays = this.expand_by_day(aYear);\n\n        for (var daykey in expandedDays) {\n          var day = expandedDays[daykey];\n          var tt = ICAL.Time.fromDayOfYear(day, aYear);\n\n          if (this.by_data.BYMONTH.indexOf(tt.month) >= 0 &&\n              this.by_data.BYMONTHDAY.indexOf(tt.day) >= 0) {\n            this.days.push(day);\n          }\n        }\n      } else if (partCount == 2 && \"BYDAY\" in parts && \"BYWEEKNO\" in parts) {\n        var expandedDays = this.expand_by_day(aYear);\n\n        for (var daykey in expandedDays) {\n          var day = expandedDays[daykey];\n          var tt = ICAL.Time.fromDayOfYear(day, aYear);\n          var weekno = tt.weekNumber(this.rule.wkst);\n\n          if (this.by_data.BYWEEKNO.indexOf(weekno)) {\n            this.days.push(day);\n          }\n        }\n      } else if (partCount == 3 &&\n                 \"BYDAY\" in parts &&\n                 \"BYWEEKNO\" in parts &&\n                 \"BYMONTHDAY\" in parts) {\n        // TODO unimplemted in libical\n      } else if (partCount == 1 && \"BYYEARDAY\" in parts) {\n        this.days = this.days.concat(this.by_data.BYYEARDAY);\n      } else {\n        this.days = [];\n      }\n      return 0;\n    },\n\n    expand_by_day: function expand_by_day(aYear) {\n\n      var days_list = [];\n      var tmp = this.last.clone();\n\n      tmp.year = aYear;\n      tmp.month = 1;\n      tmp.day = 1;\n      tmp.isDate = true;\n\n      var start_dow = tmp.dayOfWeek();\n\n      tmp.month = 12;\n      tmp.day = 31;\n      tmp.isDate = true;\n\n      var end_dow = tmp.dayOfWeek();\n      var end_year_day = tmp.dayOfYear();\n\n      for (var daykey in this.by_data.BYDAY) {\n        var day = this.by_data.BYDAY[daykey];\n        var parts = this.ruleDayOfWeek(day);\n        var pos = parts[0];\n        var dow = parts[1];\n\n        if (pos == 0) {\n          var tmp_start_doy = ((dow + 7 - start_dow) % 7) + 1;\n\n          for (var doy = tmp_start_doy; doy <= end_year_day; doy += 7) {\n            days_list.push(doy);\n          }\n\n        } else if (pos > 0) {\n          var first;\n          if (dow >= start_dow) {\n            first = dow - start_dow + 1;\n          } else {\n            first = dow - start_dow + 8;\n          }\n\n          days_list.push(first + (pos - 1) * 7);\n        } else {\n          var last;\n          pos = -pos;\n\n          if (dow <= end_dow) {\n            last = end_year_day - end_dow + dow;\n          } else {\n            last = end_year_day - end_dow + dow - 7;\n          }\n\n          days_list.push(last - (pos - 1) * 7);\n        }\n      }\n      return days_list;\n    },\n\n    is_day_in_byday: function is_day_in_byday(tt) {\n      for (var daykey in this.by_data.BYDAY) {\n        var day = this.by_data.BYDAY[daykey];\n        var parts = this.ruleDayOfWeek(day);\n        var pos = parts[0];\n        var dow = parts[1];\n        var this_dow = tt.dayOfWeek();\n\n        if ((pos == 0 && dow == this_dow) ||\n            (tt.nthWeekDay(dow, pos) == tt.day)) {\n          return 1;\n        }\n      }\n\n      return 0;\n    },\n\n    /**\n     * Checks if given value is in BYSETPOS.\n     *\n     * @param {Numeric} aPos position to check for.\n     * @return {Boolean} false unless BYSETPOS rules exist\n     *                   and the given value is present in rules.\n     */\n    check_set_position: function check_set_position(aPos) {\n      if (this.has_by_data('BYSETPOS')) {\n        var idx = this.by_data.BYSETPOS.indexOf(aPos);\n        // negative numbers are not false-y\n        return idx !== -1;\n      }\n      return false;\n    },\n\n    sort_byday_rules: function icalrecur_sort_byday_rules(aRules, aWeekStart) {\n      for (var i = 0; i < aRules.length; i++) {\n        for (var j = 0; j < i; j++) {\n          var one = this.ruleDayOfWeek(aRules[j])[1];\n          var two = this.ruleDayOfWeek(aRules[i])[1];\n          one -= aWeekStart;\n          two -= aWeekStart;\n          if (one < 0) one += 7;\n          if (two < 0) two += 7;\n\n          if (one > two) {\n            var tmp = aRules[i];\n            aRules[i] = aRules[j];\n            aRules[j] = tmp;\n          }\n        }\n      }\n    },\n\n    check_contract_restriction: function check_contract_restriction(aRuleType, v) {\n      var indexMapValue = icalrecur_iterator._indexMap[aRuleType];\n      var ruleMapValue = icalrecur_iterator._expandMap[this.rule.freq][indexMapValue];\n      var pass = false;\n\n      if (aRuleType in this.by_data &&\n          ruleMapValue == icalrecur_iterator.CONTRACT) {\n\n        var ruleType = this.by_data[aRuleType];\n\n        for (var bydatakey in ruleType) {\n          if (ruleType[bydatakey] == v) {\n            pass = true;\n            break;\n          }\n        }\n      } else {\n        // Not a contracting byrule or has no data, test passes\n        pass = true;\n      }\n      return pass;\n    },\n\n    check_contracting_rules: function check_contracting_rules() {\n      var dow = this.last.dayOfWeek();\n      var weekNo = this.last.weekNumber(this.rule.wkst);\n      var doy = this.last.dayOfYear();\n\n      return (this.check_contract_restriction(\"BYSECOND\", this.last.second) &&\n              this.check_contract_restriction(\"BYMINUTE\", this.last.minute) &&\n              this.check_contract_restriction(\"BYHOUR\", this.last.hour) &&\n              this.check_contract_restriction(\"BYDAY\", ICAL.Recur.numericDayToIcalDay(dow)) &&\n              this.check_contract_restriction(\"BYWEEKNO\", weekNo) &&\n              this.check_contract_restriction(\"BYMONTHDAY\", this.last.day) &&\n              this.check_contract_restriction(\"BYMONTH\", this.last.month) &&\n              this.check_contract_restriction(\"BYYEARDAY\", doy));\n    },\n\n    setup_defaults: function setup_defaults(aRuleType, req, deftime) {\n      var indexMapValue = icalrecur_iterator._indexMap[aRuleType];\n      var ruleMapValue = icalrecur_iterator._expandMap[this.rule.freq][indexMapValue];\n\n      if (ruleMapValue != icalrecur_iterator.CONTRACT) {\n        if (!(aRuleType in this.by_data)) {\n          this.by_data[aRuleType] = [deftime];\n        }\n        if (this.rule.freq != req) {\n          return this.by_data[aRuleType][0];\n        }\n      }\n      return deftime;\n    },\n\n    /**\n     * Convert iterator into a serialize-able object.\n     * Will preserve current iteration sequence to ensure\n     * the seamless continuation of the recurrence rule.\n     */\n    toJSON: function() {\n      var result = Object.create(null);\n\n      result.initialized = this.initialized;\n      result.rule = this.rule.toJSON();\n      result.dtstart = this.dtstart.toJSON();\n      result.by_data = this.by_data;\n      result.days = this.days;\n      result.last = this.last.toJSON();\n      result.by_indices = this.by_indices;\n      result.occurrence_number = this.occurrence_number;\n\n      return result;\n    }\n\n  };\n\n  icalrecur_iterator._indexMap = {\n    \"BYSECOND\": 0,\n    \"BYMINUTE\": 1,\n    \"BYHOUR\": 2,\n    \"BYDAY\": 3,\n    \"BYMONTHDAY\": 4,\n    \"BYYEARDAY\": 5,\n    \"BYWEEKNO\": 6,\n    \"BYMONTH\": 7,\n    \"BYSETPOS\": 8\n  };\n\n  icalrecur_iterator._expandMap = {\n    \"SECONDLY\": [1, 1, 1, 1, 1, 1, 1, 1],\n    \"MINUTELY\": [2, 1, 1, 1, 1, 1, 1, 1],\n    \"HOURLY\": [2, 2, 1, 1, 1, 1, 1, 1],\n    \"DAILY\": [2, 2, 2, 1, 1, 1, 1, 1],\n    \"WEEKLY\": [2, 2, 2, 2, 3, 3, 1, 1],\n    \"MONTHLY\": [2, 2, 2, 2, 2, 3, 3, 1],\n    \"YEARLY\": [2, 2, 2, 2, 2, 2, 2, 2]\n  };\n  icalrecur_iterator.UNKNOWN = 0;\n  icalrecur_iterator.CONTRACT = 1;\n  icalrecur_iterator.EXPAND = 2;\n  icalrecur_iterator.ILLEGAL = 3;\n\n  return icalrecur_iterator;\n\n}());\nICAL.RecurExpansion = (function() {\n  function formatTime(item) {\n    return ICAL.helpers.formatClassType(item, ICAL.Time);\n  }\n\n  function compareTime(a, b) {\n    return a.compare(b);\n  }\n\n  function isRecurringComponent(comp) {\n    return comp.hasProperty('rdate') ||\n           comp.hasProperty('rrule') ||\n           comp.hasProperty('recurrence-id');\n  }\n\n  /**\n   * Primary class for expanding recurring rules.\n   * Can take multiple rrules, rdates, exdate(s)\n   * and iterate (in order) over each next occurrence.\n   *\n   * Once initialized this class can also be serialized\n   * saved and continue iteration from the last point.\n   *\n   * NOTE: it is intended that this class is to be used\n   *       with ICAL.Event which handles recurrence exceptions.\n   *\n   * Options:\n   *  - dtstart: (ICAL.Time) start time of event (required)\n   *  - component: (ICAL.Component) component (required unless resuming)\n   *\n   * Examples:\n   *\n   *    // assuming event is a parsed ical component\n   *    var event;\n   *\n   *    var expand = new ICAL.RecurExpansion({\n   *      component: event,\n   *      start: event.getFirstPropertyValue('DTSTART')\n   *    });\n   *\n   *    // remember there are infinite rules\n   *    // so its a good idea to limit the scope\n   *    // of the iterations then resume later on.\n   *\n   *    // next is always an ICAL.Time or null\n   *    var next;\n   *\n   *    while(someCondition && (next = expand.next())) {\n   *      // do something with next\n   *    }\n   *\n   *    // save instance for later\n   *    var json = JSON.stringify(expand);\n   *\n   *    //...\n   *\n   *    // NOTE: if the component's properties have\n   *    //       changed you will need to rebuild the\n   *    //       class and start over. This only works\n   *    //       when the component's recurrence info is the same.\n   *    var expand = new ICAL.RecurExpansion(JSON.parse(json));\n   *\n   *\n   * @param {Object} options see options block.\n   */\n  function RecurExpansion(options) {\n    this.ruleDates = [];\n    this.exDates = [];\n    this.fromData(options);\n  }\n\n  RecurExpansion.prototype = {\n\n    /**\n     * True when iteration is fully completed.\n     */\n    complete: false,\n\n    /**\n     * Array of rrule iterators.\n     *\n     * @type {Array[ICAL.RecurIterator]}\n     * @private\n     */\n    ruleIterators: null,\n\n    /**\n     * Array of rdate instances.\n     *\n     * @type {Array[ICAL.Time]}\n     * @private\n     */\n    ruleDates: null,\n\n    /**\n     * Array of exdate instances.\n     *\n     * @type {Array[ICAL.Time]}\n     * @private\n     */\n    exDates: null,\n\n    /**\n     * Current position in ruleDates array.\n     * @type {Number}\n     * @private\n     */\n    ruleDateInc: 0,\n\n    /**\n     * Current position in exDates array\n     * @type {Number}\n     * @private\n     */\n    exDateInc: 0,\n\n    /**\n     * Current negative date.\n     *\n     * @type {ICAL.Time}\n     * @private\n     */\n    exDate: null,\n\n    /**\n     * Current additional date.\n     *\n     * @type {ICAL.Time}\n     * @private\n     */\n    ruleDate: null,\n\n    /**\n     * Start date of recurring rules.\n     *\n     * @type {ICAL.Time}\n     */\n    dtstart: null,\n\n    /**\n     * Last expanded time\n     *\n     * @type {ICAL.Time}\n     */\n    last: null,\n\n    fromData: function(options) {\n      var start = ICAL.helpers.formatClassType(options.dtstart, ICAL.Time);\n\n      if (!start) {\n        throw new Error('.dtstart (ICAL.Time) must be given');\n      } else {\n        this.dtstart = start;\n      }\n\n      if (options.component) {\n        this._init(options.component);\n      } else {\n        this.last = formatTime(options.last) || start.clone();\n\n        if (!options.ruleIterators) {\n          throw new Error('.ruleIterators or .component must be given');\n        }\n\n        this.ruleIterators = options.ruleIterators.map(function(item) {\n          return ICAL.helpers.formatClassType(item, ICAL.RecurIterator);\n        });\n\n        this.ruleDateInc = options.ruleDateInc;\n        this.exDateInc = options.exDateInc;\n\n        if (options.ruleDates) {\n          this.ruleDates = options.ruleDates.map(formatTime);\n          this.ruleDate = this.ruleDates[this.ruleDateInc];\n        }\n\n        if (options.exDates) {\n          this.exDates = options.exDates.map(formatTime);\n          this.exDate = this.exDates[this.exDateInc];\n        }\n\n        if (typeof(options.complete) !== 'undefined') {\n          this.complete = options.complete;\n        }\n      }\n    },\n\n    next: function() {\n      var iter;\n      var ruleOfDay;\n      var next;\n      var compare;\n\n      var maxTries = 500;\n      var currentTry = 0;\n\n      while (true) {\n        if (currentTry++ > maxTries) {\n          throw new Error(\n            'max tries have occured, rule may be impossible to forfill.'\n          );\n        }\n\n        next = this.ruleDate;\n        iter = this._nextRecurrenceIter(this.last);\n\n        // no more matches\n        // because we increment the rule day or rule\n        // _after_ we choose a value this should be\n        // the only spot where we need to worry about the\n        // end of events.\n        if (!next && !iter) {\n          // there are no more iterators or rdates\n          this.complete = true;\n          break;\n        }\n\n        // no next rule day or recurrence rule is first.\n        if (!next || (iter && next.compare(iter.last) > 0)) {\n          // must be cloned, recur will reuse the time element.\n          next = iter.last.clone();\n          // move to next so we can continue\n          iter.next();\n        }\n\n        // if the ruleDate is still next increment it.\n        if (this.ruleDate === next) {\n          this._nextRuleDay();\n        }\n\n        this.last = next;\n\n        // check the negative rules\n        if (this.exDate) {\n          compare = this.exDate.compare(this.last);\n\n          if (compare < 0) {\n            this._nextExDay();\n          }\n\n          // if the current rule is excluded skip it.\n          if (compare === 0) {\n            this._nextExDay();\n            continue;\n          }\n        }\n\n        //XXX: The spec states that after we resolve the final\n        //     list of dates we execute exdate this seems somewhat counter\n        //     intuitive to what I have seen most servers do so for now\n        //     I exclude based on the original date not the one that may\n        //     have been modified by the exception.\n        return this.last;\n      }\n    },\n\n    /**\n     * Converts object into a serialize-able format.\n     */\n    toJSON: function() {\n      function toJSON(item) {\n        return item.toJSON();\n      }\n\n      var result = Object.create(null);\n      result.ruleIterators = this.ruleIterators.map(toJSON);\n\n      if (this.ruleDates) {\n        result.ruleDates = this.ruleDates.map(toJSON);\n      }\n\n      if (this.exDates) {\n        result.exDates = this.exDates.map(toJSON);\n      }\n\n      result.ruleDateInc = this.ruleDateInc;\n      result.exDateInc = this.exDateInc;\n      result.last = this.last.toJSON();\n      result.dtstart = this.dtstart.toJSON();\n      result.complete = this.complete;\n\n      return result;\n    },\n\n\n    _extractDates: function(component, property) {\n      function handleProp(prop) {\n        idx = ICAL.helpers.binsearchInsert(\n          result,\n          prop,\n          compareTime\n        );\n\n        // ordered insert\n        result.splice(idx, 0, prop);\n      }\n\n      var result = [];\n      var props = component.getAllProperties(property);\n      var len = props.length;\n      var i = 0;\n      var prop;\n\n      var idx;\n\n      for (; i < len; i++) {\n        props[i].getValues().forEach(handleProp);\n      }\n\n      return result;\n    },\n\n    _init: function(component) {\n      this.ruleIterators = [];\n\n      this.last = this.dtstart.clone();\n\n      // to provide api consistency non-recurring\n      // events can also use the iterator though it will\n      // only return a single time.\n      if (!isRecurringComponent(component)) {\n        this.ruleDate = this.last.clone();\n        this.complete = true;\n        return;\n      }\n\n      if (component.hasProperty('rdate')) {\n        this.ruleDates = this._extractDates(component, 'rdate');\n\n        // special hack for cases where first rdate is prior\n        // to the start date. We only check for the first rdate.\n        // This is mostly for google's crazy recurring date logic\n        // (contacts birthdays).\n        if ((this.ruleDates[0]) &&\n            (this.ruleDates[0].compare(this.dtstart) < 0)) {\n\n          this.ruleDateInc = 0;\n          this.last = this.ruleDates[0].clone();\n        } else {\n          this.ruleDateInc = ICAL.helpers.binsearchInsert(\n            this.ruleDates,\n            this.last,\n            compareTime\n          );\n        }\n\n        this.ruleDate = this.ruleDates[this.ruleDateInc];\n      }\n\n      if (component.hasProperty('rrule')) {\n        var rules = component.getAllProperties('rrule');\n        var i = 0;\n        var len = rules.length;\n\n        var rule;\n        var iter;\n\n        for (; i < len; i++) {\n          rule = rules[i].getFirstValue();\n          iter = rule.iterator(this.dtstart);\n          this.ruleIterators.push(iter);\n\n          // increment to the next occurrence so future\n          // calls to next return times beyond the initial iteration.\n          // XXX: I find this suspicious might be a bug?\n          iter.next();\n        }\n      }\n\n      if (component.hasProperty('exdate')) {\n        this.exDates = this._extractDates(component, 'exdate');\n        // if we have a .last day we increment the index to beyond it.\n        this.exDateInc = ICAL.helpers.binsearchInsert(\n          this.exDates,\n          this.last,\n          compareTime\n        );\n\n        this.exDate = this.exDates[this.exDateInc];\n      }\n    },\n\n    _nextExDay: function() {\n      this.exDate = this.exDates[++this.exDateInc];\n    },\n\n    _nextRuleDay: function() {\n      this.ruleDate = this.ruleDates[++this.ruleDateInc];\n    },\n\n    /**\n     * Find and return the recurrence rule with the most\n     * recent event and return it.\n     *\n     * @return {Object} iterator.\n     */\n    _nextRecurrenceIter: function() {\n      var iters = this.ruleIterators;\n\n      if (iters.length === 0) {\n        return null;\n      }\n\n      var len = iters.length;\n      var iter;\n      var iterTime;\n      var iterIdx = 0;\n      var chosenIter;\n\n      // loop through each iterator\n      for (; iterIdx < len; iterIdx++) {\n        iter = iters[iterIdx];\n        iterTime = iter.last;\n\n        // if iteration is complete\n        // then we must exclude it from\n        // the search and remove it.\n        if (iter.completed) {\n          len--;\n          if (iterIdx !== 0) {\n            iterIdx--;\n          }\n          iters.splice(iterIdx, 1);\n          continue;\n        }\n\n        // find the most recent possible choice\n        if (!chosenIter || chosenIter.last.compare(iterTime) > 0) {\n          // that iterator is saved\n          chosenIter = iter;\n        }\n      }\n\n      // the chosen iterator is returned but not mutated\n      // this iterator contains the most recent event.\n      return chosenIter;\n    }\n\n  };\n\n  return RecurExpansion;\n\n}());\nICAL.Event = (function() {\n\n  function compareRangeException(a, b) {\n    if (a[0] > b[0]) return 1;\n    if (b[0] > a[0]) return -1;\n    return 0;\n  }\n\n  function Event(component, options) {\n    if (!(component instanceof ICAL.Component)) {\n      options = component;\n      component = null;\n    }\n\n    if (component) {\n      this.component = component;\n    } else {\n      this.component = new ICAL.Component('vevent');\n    }\n\n    this._rangeExceptionCache = Object.create(null);\n    this.exceptions = Object.create(null);\n    this.rangeExceptions = [];\n\n    if (options && options.strictExceptions) {\n      this.strictExceptions = options.strictExceptions;\n    }\n\n    if (options && options.exceptions) {\n      options.exceptions.forEach(this.relateException, this);\n    }\n  }\n\n  Event.prototype = {\n\n    THISANDFUTURE: 'THISANDFUTURE',\n\n    /**\n     * List of related event exceptions.\n     *\n     * @type {Array[ICAL.Event]}\n     */\n    exceptions: null,\n\n    /**\n     * When true will verify exceptions are related by their UUID.\n     *\n     * @type {Boolean}\n     */\n    strictExceptions: false,\n\n    /**\n     * Relates a given event exception to this object.\n     * If the given component does not share the UID of\n     * this event it cannot be related and will throw an\n     * exception.\n     *\n     * If this component is an exception it cannot have other\n     * exceptions related to it.\n     *\n     * @param {ICAL.Component|ICAL.Event} obj component or event.\n     */\n    relateException: function(obj) {\n      if (this.isRecurrenceException()) {\n        throw new Error('cannot relate exception to exceptions');\n      }\n\n      if (obj instanceof ICAL.Component) {\n        obj = new ICAL.Event(obj);\n      }\n\n      if (this.strictExceptions && obj.uid !== this.uid) {\n        throw new Error('attempted to relate unrelated exception');\n      }\n\n      var id = obj.recurrenceId.toString();\n\n      // we don't sort or manage exceptions directly\n      // here the recurrence expander handles that.\n      this.exceptions[id] = obj;\n\n      // index RANGE=THISANDFUTURE exceptions so we can\n      // look them up later in getOccurrenceDetails.\n      if (obj.modifiesFuture()) {\n        var item = [\n          obj.recurrenceId.toUnixTime(), id\n        ];\n\n        // we keep them sorted so we can find the nearest\n        // value later on...\n        var idx = ICAL.helpers.binsearchInsert(\n          this.rangeExceptions,\n          item,\n          compareRangeException\n        );\n\n        this.rangeExceptions.splice(idx, 0, item);\n      }\n    },\n\n    /**\n     * If this record is an exception and has the RANGE=THISANDFUTURE value.\n     *\n     * @return {Boolean} true when is exception with range.\n     */\n    modifiesFuture: function() {\n      var range = this.component.getFirstPropertyValue('range');\n      return range === this.THISANDFUTURE;\n    },\n\n    /**\n     * Finds the range exception nearest to the given date.\n     *\n     * @param {ICAL.Time} time usually an occurrence time of an event.\n     * @return {ICAL.Event|Null} the related event/exception or null.\n     */\n    findRangeException: function(time) {\n      if (!this.rangeExceptions.length) {\n        return null;\n      }\n\n      var utc = time.toUnixTime();\n      var idx = ICAL.helpers.binsearchInsert(\n        this.rangeExceptions,\n        [utc],\n        compareRangeException\n      );\n\n      idx -= 1;\n\n      // occurs before\n      if (idx < 0) {\n        return null;\n      }\n\n      var rangeItem = this.rangeExceptions[idx];\n\n      /* istanbul ignore next: sanity check only */\n      if (utc < rangeItem[0]) {\n        return null;\n      }\n\n      return rangeItem[1];\n    },\n\n    /**\n     * Returns the occurrence details based on its start time.\n     * If the occurrence has an exception will return the details\n     * for that exception.\n     *\n     * NOTE: this method is intend to be used in conjunction\n     *       with the #iterator method.\n     *\n     * @param {ICAL.Time} occurrence time occurrence.\n     */\n    getOccurrenceDetails: function(occurrence) {\n      var id = occurrence.toString();\n      var utcId = occurrence.convertToZone(ICAL.Timezone.utcTimezone).toString();\n      var item;\n      var result = {\n        //XXX: Clone?\n        recurrenceId: occurrence\n      };\n\n      if (id in this.exceptions) {\n        item = result.item = this.exceptions[id];\n        result.startDate = item.startDate;\n        result.endDate = item.endDate;\n        result.item = item;\n      } else if (utcId in this.exceptions) {\n        item = this.exceptions[utcId];\n        result.startDate = item.startDate;\n        result.endDate = item.endDate;\n        result.item = item;\n      } else {\n        // range exceptions (RANGE=THISANDFUTURE) have a\n        // lower priority then direct exceptions but\n        // must be accounted for first. Their item is\n        // always the first exception with the range prop.\n        var rangeExceptionId = this.findRangeException(\n          occurrence\n        );\n        var end;\n\n        if (rangeExceptionId) {\n          var exception = this.exceptions[rangeExceptionId];\n\n          // range exception must modify standard time\n          // by the difference (if any) in start/end times.\n          result.item = exception;\n\n          var startDiff = this._rangeExceptionCache[rangeExceptionId];\n\n          if (!startDiff) {\n            var original = exception.recurrenceId.clone();\n            var newStart = exception.startDate.clone();\n\n            // zones must be same otherwise subtract may be incorrect.\n            original.zone = newStart.zone;\n            startDiff = newStart.subtractDate(original);\n\n            this._rangeExceptionCache[rangeExceptionId] = startDiff;\n          }\n\n          var start = occurrence.clone();\n          start.zone = exception.startDate.zone;\n          start.addDuration(startDiff);\n\n          end = start.clone();\n          end.addDuration(exception.duration);\n\n          result.startDate = start;\n          result.endDate = end;\n        } else {\n          // no range exception standard expansion\n          end = occurrence.clone();\n          end.addDuration(this.duration);\n\n          result.endDate = end;\n          result.startDate = occurrence;\n          result.item = this;\n        }\n      }\n\n      return result;\n    },\n\n    /**\n     * Builds a recur expansion instance for a specific\n     * point in time (defaults to startDate).\n     *\n     * @return {ICAL.RecurExpansion} expander object.\n     */\n    iterator: function(startTime) {\n      return new ICAL.RecurExpansion({\n        component: this.component,\n        dtstart: startTime || this.startDate\n      });\n    },\n\n    isRecurring: function() {\n      var comp = this.component;\n      return comp.hasProperty('rrule') || comp.hasProperty('rdate');\n    },\n\n    isRecurrenceException: function() {\n      return this.component.hasProperty('recurrence-id');\n    },\n\n    /**\n     * Returns the types of recurrences this event may have.\n     *\n     * Returned as an object with the following possible keys:\n     *\n     *    - YEARLY\n     *    - MONTHLY\n     *    - WEEKLY\n     *    - DAILY\n     *    - MINUTELY\n     *    - SECONDLY\n     *\n     * @return {Object} object of recurrence flags.\n     */\n    getRecurrenceTypes: function() {\n      var rules = this.component.getAllProperties('rrule');\n      var i = 0;\n      var len = rules.length;\n      var result = Object.create(null);\n\n      for (; i < len; i++) {\n        var value = rules[i].getFirstValue();\n        result[value.freq] = true;\n      }\n\n      return result;\n    },\n\n    get uid() {\n      return this._firstProp('uid');\n    },\n\n    set uid(value) {\n      this._setProp('uid', value);\n    },\n\n    get startDate() {\n      return this._firstProp('dtstart');\n    },\n\n    set startDate(value) {\n      this._setTime('dtstart', value);\n    },\n\n    get endDate() {\n      var endDate = this._firstProp('dtend');\n      if (!endDate) {\n          var duration = this._firstProp('duration');\n          endDate = this.startDate.clone();\n          if (duration) {\n              endDate.addDuration(duration);\n          } else if (endDate.isDate) {\n              endDate.day += 1;\n          }\n      }\n      return endDate;\n    },\n\n    set endDate(value) {\n      this._setTime('dtend', value);\n    },\n\n    get duration() {\n      var duration = this._firstProp('duration');\n      if (!duration) {\n        return this.endDate.subtractDate(this.startDate);\n      }\n      return duration;\n    },\n\n    get location() {\n      return this._firstProp('location');\n    },\n\n    set location(value) {\n      return this._setProp('location', value);\n    },\n\n    get attendees() {\n      //XXX: This is way lame we should have a better\n      //     data structure for this later.\n      return this.component.getAllProperties('attendee');\n    },\n\n    get summary() {\n      return this._firstProp('summary');\n    },\n\n    set summary(value) {\n      this._setProp('summary', value);\n    },\n\n    get description() {\n      return this._firstProp('description');\n    },\n\n    set description(value) {\n      this._setProp('description', value);\n    },\n\n    get organizer() {\n      return this._firstProp('organizer');\n    },\n\n    set organizer(value) {\n      this._setProp('organizer', value);\n    },\n\n    get sequence() {\n      return this._firstProp('sequence');\n    },\n\n    set sequence(value) {\n      this._setProp('sequence', value);\n    },\n\n    get recurrenceId() {\n      return this._firstProp('recurrence-id');\n    },\n\n    set recurrenceId(value) {\n      this._setProp('recurrence-id', value);\n    },\n\n    /**\n     * set/update a time property's value.\n     * This will also update the TZID of the property.\n     *\n     * TODO: this method handles the case where we are switching\n     * from a known timezone to an implied timezone (one without TZID).\n     * This does _not_ handle the case of moving between a known\n     *  (by TimezoneService) timezone to an unknown timezone...\n     *\n     * We will not add/remove/update the VTIMEZONE subcomponents\n     *  leading to invalid ICAL data...\n     */\n    _setTime: function(propName, time) {\n      var prop = this.component.getFirstProperty(propName);\n\n      if (!prop) {\n        prop = new ICAL.Property(propName);\n        this.component.addProperty(prop);\n      }\n\n      // utc and local don't get a tzid\n      if (\n        time.zone === ICAL.Timezone.localTimezone ||\n        time.zone === ICAL.Timezone.utcTimezone\n      ) {\n        // remove the tzid\n        prop.removeParameter('tzid');\n      } else {\n        prop.setParameter('tzid', time.zone.tzid);\n      }\n\n      prop.setValue(time);\n    },\n\n    _setProp: function(name, value) {\n      this.component.updatePropertyWithValue(name, value);\n    },\n\n    _firstProp: function(name) {\n      return this.component.getFirstPropertyValue(name);\n    },\n\n    toString: function() {\n      return this.component.toString();\n    }\n\n  };\n\n  return Event;\n\n}());\nICAL.ComponentParser = (function() {\n\n  /**\n   * Component parser initializer.\n   *\n   * Usage:\n   *\n   *    var options = {\n   *      // when false no events will be emitted for type\n   *      parseEvent: true,\n   *      parseTimezone: true\n   *    };\n   *\n   *    var parser = new ICAL.ComponentParser(options);\n   *\n   *    parser.onevent() {\n   *      //...\n   *    }\n   *\n   *    // ontimezone, etc...\n   *\n   *    parser.oncomplete = function() {\n   *\n   *    };\n   *\n   *    parser.process(string | component);\n   *\n   *\n   * @param {Object} options component parser options.\n   */\n  function ComponentParser(options) {\n    if (typeof(options) === 'undefined') {\n      options = {};\n    }\n\n    var key;\n    for (key in options) {\n      /* istanbul ignore else */\n      if (options.hasOwnProperty(key)) {\n        this[key] = options[key];\n      }\n    }\n  }\n\n  ComponentParser.prototype = {\n\n    /**\n     * When true parse events\n     *\n     * @type {Boolean}\n     */\n    parseEvent: true,\n\n    /**\n     * when true parse timezones\n     *\n     * @type {Boolean}\n     */\n    parseTimezone: true,\n\n\n    /* SAX like events here for reference */\n\n    /**\n     * Fired when parsing is complete\n     */\n    oncomplete: /* istanbul ignore next */ function() {},\n\n    /**\n     * Fired if an error occurs during parsing.\n     *\n     * @param {Error} err details of error.\n     */\n    onerror: /* istanbul ignore next */ function(err) {},\n\n    /**\n     * Fired when a top level component (vtimezone) is found\n     *\n     * @param {ICAL.Timezone} timezone object.\n     */\n    ontimezone: /* istanbul ignore next */ function(component) {},\n\n    /*\n     * Fired when a top level component (VEVENT) is found.\n     * @param {ICAL.Event} component top level component.\n     */\n    onevent: /* istanbul ignore next */ function(component) {},\n\n    /**\n     * Process a string or parse ical object.\n     * This function itself will return nothing but\n     * will start the parsing process.\n     *\n     * Events must be registered prior to calling this method.\n     *\n     * @param {String|Object} ical string or parsed ical object.\n     */\n    process: function(ical) {\n      //TODO: this is sync now in the future we will have a incremental parser.\n      if (typeof(ical) === 'string') {\n        ical = ICAL.parse(ical);\n      }\n\n      if (!(ical instanceof ICAL.Component)) {\n        ical = new ICAL.Component(ical);\n      }\n\n      var components = ical.getAllSubcomponents();\n      var i = 0;\n      var len = components.length;\n      var component;\n\n      for (; i < len; i++) {\n        component = components[i];\n\n        switch (component.name) {\n          case 'vtimezone':\n            if (this.parseTimezone) {\n              var tzid = component.getFirstPropertyValue('tzid');\n              if (tzid) {\n                this.ontimezone(new ICAL.Timezone({\n                  tzid: tzid,\n                  component: component\n                }));\n              }\n            }\n            break;\n          case 'vevent':\n            if (this.parseEvent) {\n              this.onevent(new ICAL.Event(component));\n            }\n            break;\n          default:\n            continue;\n        }\n      }\n\n      //XXX: ideally we should do a \"nextTick\" here\n      //     so in all cases this is actually async.\n      this.oncomplete();\n    }\n  };\n\n  return ComponentParser;\n\n}());\n"]}