mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 11:50:00 +00:00
Merge pull request #2048 from rejas/issue_1926
Updated ical library to latest version
This commit is contained in:
commit
3b442d4bfc
@ -38,6 +38,7 @@ _This release is scheduled to be released on 2020-07-01._
|
||||
- Fix the use of "maxNumberOfDays" in the module "weatherforecast" [#2018](https://github.com/MichMich/MagicMirror/issues/2018)
|
||||
- Throw error when check_config fails [#1928](https://github.com/MichMich/MagicMirror/issues/1928)
|
||||
- Bug fix related to 'maxEntries' not displaying Calendar events. [#2050](https://github.com/MichMich/MagicMirror/issues/2050)
|
||||
- Updated ical library to latest version [#1926](https://github.com/MichMich/MagicMirror/issues/1926)
|
||||
|
||||
## [2.11.0] - 2020-04-01
|
||||
|
||||
|
@ -5,27 +5,28 @@
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const Log = require("../../../js/logger.js");
|
||||
const ical = require("./vendor/ical.js");
|
||||
const ical = require("ical");
|
||||
const moment = require("moment");
|
||||
const request = require("request");
|
||||
|
||||
var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumberOfDays, auth, includePastEvents) {
|
||||
var self = this;
|
||||
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumberOfDays, auth, includePastEvents) {
|
||||
const self = this;
|
||||
|
||||
var reloadTimer = null;
|
||||
var events = [];
|
||||
let reloadTimer = null;
|
||||
let events = [];
|
||||
|
||||
var fetchFailedCallback = function () {};
|
||||
var eventsReceivedCallback = function () {};
|
||||
let fetchFailedCallback = function () {};
|
||||
let eventsReceivedCallback = function () {};
|
||||
|
||||
/* fetchCalendar()
|
||||
* Initiates calendar fetch.
|
||||
*/
|
||||
var fetchCalendar = function () {
|
||||
const fetchCalendar = function () {
|
||||
clearTimeout(reloadTimer);
|
||||
reloadTimer = null;
|
||||
|
||||
var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
||||
var opts = {
|
||||
const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
||||
const opts = {
|
||||
headers: {
|
||||
"User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)"
|
||||
},
|
||||
@ -40,41 +41,40 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
} else {
|
||||
opts.auth = {
|
||||
user: auth.user,
|
||||
pass: auth.pass
|
||||
pass: auth.pass,
|
||||
sendImmediately: auth.method !== "digest"
|
||||
};
|
||||
|
||||
if (auth.method === "digest") {
|
||||
opts.auth.sendImmediately = false;
|
||||
} else {
|
||||
opts.auth.sendImmediately = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ical.fromURL(url, opts, function (err, data) {
|
||||
request(url, opts, function (err, r, requestData) {
|
||||
if (err) {
|
||||
fetchFailedCallback(self, err);
|
||||
scheduleTimer();
|
||||
return;
|
||||
} else if (r.statusCode !== 200) {
|
||||
fetchFailedCallback(self, r.statusCode + ": " + r.statusMessage);
|
||||
scheduleTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
var newEvents = [];
|
||||
const data = ical.parseICS(requestData);
|
||||
const newEvents = [];
|
||||
|
||||
// limitFunction doesn't do much limiting, see comment re: the dates array in rrule section below as to why we need to do the filtering ourselves
|
||||
var limitFunction = function (date, i) {
|
||||
const limitFunction = function (date, i) {
|
||||
return true;
|
||||
};
|
||||
|
||||
var eventDate = function (event, time) {
|
||||
const eventDate = function (event, time) {
|
||||
return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
|
||||
};
|
||||
|
||||
for (var e in data) {
|
||||
var event = data[e];
|
||||
var now = new Date();
|
||||
var today = moment().startOf("day").toDate();
|
||||
var future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat.
|
||||
var past = today;
|
||||
Object.entries(data).forEach(([key, event]) => {
|
||||
const now = new Date();
|
||||
const today = moment().startOf("day").toDate();
|
||||
const future = moment().startOf("day").add(maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat.
|
||||
let past = today;
|
||||
|
||||
if (includePastEvents) {
|
||||
past = moment().startOf("day").subtract(maximumNumberOfDays, "days").toDate();
|
||||
@ -82,7 +82,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
|
||||
// FIXME: Ugly fix to solve the facebook birthday issue.
|
||||
// Otherwise, the recurring events only show the birthday for next year.
|
||||
var isFacebookBirthday = false;
|
||||
let isFacebookBirthday = false;
|
||||
if (typeof event.uid !== "undefined") {
|
||||
if (event.uid.indexOf("@facebook.com") !== -1) {
|
||||
isFacebookBirthday = true;
|
||||
@ -90,13 +90,13 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
}
|
||||
|
||||
if (event.type === "VEVENT") {
|
||||
var startDate = eventDate(event, "start");
|
||||
var endDate;
|
||||
let startDate = eventDate(event, "start");
|
||||
let endDate;
|
||||
|
||||
if (typeof event.end !== "undefined") {
|
||||
endDate = eventDate(event, "end");
|
||||
} else if (typeof event.duration !== "undefined") {
|
||||
var dur = moment.duration(event.duration);
|
||||
endDate = startDate.clone().add(dur);
|
||||
endDate = startDate.clone().add(moment.duration(event.duration));
|
||||
} else {
|
||||
if (!isFacebookBirthday) {
|
||||
endDate = startDate;
|
||||
@ -105,20 +105,20 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the duration f the event for use with recurring events.
|
||||
var duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x"));
|
||||
// calculate the duration of the event for use with recurring events.
|
||||
let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x"));
|
||||
|
||||
if (event.start.length === 8) {
|
||||
startDate = startDate.startOf("day");
|
||||
}
|
||||
|
||||
var title = getTitleFromEvent(event);
|
||||
const title = getTitleFromEvent(event);
|
||||
|
||||
var excluded = false,
|
||||
let excluded = false,
|
||||
dateFilter = null;
|
||||
|
||||
for (var f in excludedEvents) {
|
||||
var filter = excludedEvents[f],
|
||||
for (let f in excludedEvents) {
|
||||
let filter = excludedEvents[f],
|
||||
testTitle = title.toLowerCase(),
|
||||
until = null,
|
||||
useRegex = false,
|
||||
@ -161,16 +161,19 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
}
|
||||
|
||||
if (excluded) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
var location = event.location || false;
|
||||
var geo = event.geo || false;
|
||||
var description = event.description || false;
|
||||
const location = event.location || false;
|
||||
const geo = event.geo || false;
|
||||
const description = event.description || false;
|
||||
|
||||
if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) {
|
||||
var rule = event.rrule;
|
||||
var addedEvents = 0;
|
||||
const rule = event.rrule;
|
||||
let addedEvents = 0;
|
||||
|
||||
const pastMoment = moment(past);
|
||||
const futureMoment = moment(future);
|
||||
|
||||
// can cause problems with e.g. birthdays before 1900
|
||||
if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) {
|
||||
@ -179,28 +182,24 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
}
|
||||
|
||||
// For recurring events, get the set of start dates that fall within the range
|
||||
// of dates we"re looking for.
|
||||
// of dates we're looking for.
|
||||
// kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time
|
||||
var pastLocal = moment(past).subtract(past.getTimezoneOffset(), "minutes").toDate();
|
||||
var futureLocal = moment(future).subtract(future.getTimezoneOffset(), "minutes").toDate();
|
||||
var datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction);
|
||||
var dates = datesLocal.map(function (dateLocal) {
|
||||
var date = moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate();
|
||||
return date;
|
||||
const pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate();
|
||||
const futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate();
|
||||
const datesLocal = rule.between(pastLocal, futureLocal, true, limitFunction);
|
||||
const dates = datesLocal.map(function (dateLocal) {
|
||||
return moment(dateLocal).add(dateLocal.getTimezoneOffset(), "minutes").toDate();
|
||||
});
|
||||
|
||||
// The "dates" array contains the set of dates within our desired date range range that are valid
|
||||
// for the recurrence rule. *However*, it"s possible for us to have a specific recurrence that
|
||||
// for the recurrence rule. *However*, it's possible for us to have a specific recurrence that
|
||||
// had its date changed from outside the range to inside the range. For the time being,
|
||||
// we"ll handle this by adding *all* recurrence entries into the set of dates that we check,
|
||||
// because the logic below will filter out any recurrences that don"t actually belong within
|
||||
// we'll handle this by adding *all* recurrence entries into the set of dates that we check,
|
||||
// because the logic below will filter out any recurrences that don't actually belong within
|
||||
// our display range.
|
||||
// Would be great if there was a better way to handle this.
|
||||
if (event.recurrences !== undefined) {
|
||||
var pastMoment = moment(past);
|
||||
var futureMoment = moment(future);
|
||||
|
||||
for (var r in event.recurrences) {
|
||||
for (let r in event.recurrences) {
|
||||
// Only add dates that weren't already in the range we added from the rrule so that
|
||||
// we don"t double-add those events.
|
||||
if (moment(new Date(r)).isBetween(pastMoment, futureMoment) !== true) {
|
||||
@ -210,25 +209,25 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
}
|
||||
|
||||
// Loop through the set of date entries to see which recurrences should be added to our event list.
|
||||
for (var d in dates) {
|
||||
var date = dates[d];
|
||||
for (let d in dates) {
|
||||
const date = dates[d];
|
||||
// ical.js started returning recurrences and exdates as ISOStrings without time information.
|
||||
// .toISOString().substring(0,10) is the method they use to calculate keys, so we'll do the same
|
||||
// (see https://github.com/peterbraden/ical.js/pull/84 )
|
||||
var dateKey = date.toISOString().substring(0, 10);
|
||||
var curEvent = event;
|
||||
var showRecurrence = true;
|
||||
const dateKey = date.toISOString().substring(0, 10);
|
||||
let curEvent = event;
|
||||
let showRecurrence = true;
|
||||
|
||||
startDate = moment(date);
|
||||
|
||||
// For each date that we"re checking, it"s possible that there is a recurrence override for that one day.
|
||||
// For each date that we're checking, it's possible that there is a recurrence override for that one day.
|
||||
if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) {
|
||||
// We found an override, so for this recurrence, use a potentially different title, start date, and duration.
|
||||
curEvent = curEvent.recurrences[dateKey];
|
||||
startDate = moment(curEvent.start);
|
||||
duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x"));
|
||||
}
|
||||
// If there"s no recurrence override, check for an exception date. Exception dates represent exceptions to the rule.
|
||||
// If there's no recurrence override, check for an exception date. Exception dates represent exceptions to the rule.
|
||||
else if (curEvent.exdate !== undefined && curEvent.exdate[dateKey] !== undefined) {
|
||||
// This date is an exception date, which means we should skip it in the recurrence pattern.
|
||||
showRecurrence = false;
|
||||
@ -239,7 +238,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
endDate = endDate.endOf("day");
|
||||
}
|
||||
|
||||
var recurrenceTitle = getTitleFromEvent(curEvent);
|
||||
const recurrenceTitle = getTitleFromEvent(curEvent);
|
||||
|
||||
// If this recurrence ends before the start of the date range, or starts after the end of the date range, don"t add
|
||||
// it to the event list.
|
||||
@ -269,32 +268,32 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
// end recurring event parsing
|
||||
} else {
|
||||
// Single event.
|
||||
var fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event);
|
||||
const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event);
|
||||
|
||||
if (includePastEvents) {
|
||||
// Past event is too far in the past, so skip.
|
||||
if (endDate < past) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// It's not a fullday event, and it is in the past, so skip.
|
||||
if (!fullDayEvent && endDate < new Date()) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// It's a fullday event, and it is before today, So skip.
|
||||
if (fullDayEvent && endDate <= today) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// It exceeds the maximumNumberOfDays limit, so skip.
|
||||
if (startDate > future) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeFilterApplies(now, endDate, dateFilter)) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already
|
||||
@ -315,7 +314,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
newEvents.sort(function (a, b) {
|
||||
return a.startDate - b.startDate;
|
||||
@ -331,7 +330,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
/* scheduleTimer()
|
||||
* Schedule the timer for the next update.
|
||||
*/
|
||||
var scheduleTimer = function () {
|
||||
const scheduleTimer = function () {
|
||||
clearTimeout(reloadTimer);
|
||||
reloadTimer = setTimeout(function () {
|
||||
fetchCalendar();
|
||||
@ -345,14 +344,14 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
*
|
||||
* return bool - The event is a fullday event.
|
||||
*/
|
||||
var isFullDayEvent = function (event) {
|
||||
const isFullDayEvent = function (event) {
|
||||
if (event.start.length === 8 || event.start.dateOnly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var start = event.start || 0;
|
||||
var startDate = new Date(start);
|
||||
var end = event.end || 0;
|
||||
const start = event.start || 0;
|
||||
const startDate = new Date(start);
|
||||
const end = event.end || 0;
|
||||
if ((end - start) % (24 * 60 * 60 * 1000) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) {
|
||||
// Is 24 hours, and starts on the middle of the night.
|
||||
return true;
|
||||
@ -370,11 +369,11 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
*
|
||||
* return bool - The event should be filtered out
|
||||
*/
|
||||
var timeFilterApplies = function (now, endDate, filter) {
|
||||
const timeFilterApplies = function (now, endDate, filter) {
|
||||
if (filter) {
|
||||
var until = filter.split(" "),
|
||||
const until = filter.split(" "),
|
||||
value = parseInt(until[0]),
|
||||
increment = until[1].slice("-1") === "s" ? until[1] : until[1] + "s", // Massage the data for moment js
|
||||
increment = until[1].slice(-1) === "s" ? until[1] : until[1] + "s", // Massage the data for moment js
|
||||
filterUntil = moment(endDate.format()).subtract(value, increment);
|
||||
|
||||
return now < filterUntil.format("x");
|
||||
@ -390,8 +389,8 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
*
|
||||
* return string - The title of the event, or "Event" if no title is found.
|
||||
*/
|
||||
var getTitleFromEvent = function (event) {
|
||||
var title = "Event";
|
||||
const getTitleFromEvent = function (event) {
|
||||
let title = "Event";
|
||||
if (event.summary) {
|
||||
title = typeof event.summary.val !== "undefined" ? event.summary.val : event.summary;
|
||||
} else if (event.description) {
|
||||
@ -401,7 +400,7 @@ var CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumNumb
|
||||
return title;
|
||||
};
|
||||
|
||||
var testTitleByFilter = function (title, filter, useRegex, regexFlags) {
|
||||
const testTitleByFilter = function (title, filter, useRegex, regexFlags) {
|
||||
if (useRegex) {
|
||||
// Assume if leading slash, there is also trailing slash
|
||||
if (filter[0] === "/") {
|
||||
|
@ -5,24 +5,23 @@
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const CalendarFetcher = require("./calendarfetcher.js");
|
||||
|
||||
var CalendarFetcher = require("./calendarfetcher.js");
|
||||
|
||||
var url = "https://calendar.google.com/calendar/ical/pkm1t2uedjbp0uvq1o7oj1jouo%40group.calendar.google.com/private-08ba559f89eec70dd74bbd887d0a3598/basic.ics"; // Standard test URL
|
||||
// var url = "https://www.googleapis.com/calendar/v3/calendars/primary/events/"; // URL for Bearer auth (must be configured in Google OAuth2 first)
|
||||
var fetchInterval = 60 * 60 * 1000;
|
||||
var maximumEntries = 10;
|
||||
var maximumNumberOfDays = 365;
|
||||
var user = "magicmirror";
|
||||
var pass = "MyStrongPass";
|
||||
var auth = {
|
||||
const url = "https://calendar.google.com/calendar/ical/pkm1t2uedjbp0uvq1o7oj1jouo%40group.calendar.google.com/private-08ba559f89eec70dd74bbd887d0a3598/basic.ics"; // Standard test URL
|
||||
//const url = "https://www.googleapis.com/calendar/v3/calendars/primary/events/"; // URL for Bearer auth (must be configured in Google OAuth2 first)
|
||||
const fetchInterval = 60 * 60 * 1000;
|
||||
const maximumEntries = 10;
|
||||
const maximumNumberOfDays = 365;
|
||||
const user = "magicmirror";
|
||||
const pass = "MyStrongPass";
|
||||
const auth = {
|
||||
user: user,
|
||||
pass: pass
|
||||
};
|
||||
|
||||
console.log("Create fetcher ...");
|
||||
|
||||
var fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth);
|
||||
const fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth);
|
||||
|
||||
fetcher.onReceive(function (fetcher) {
|
||||
console.log(fetcher.events());
|
||||
|
@ -1,4 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "8.9"
|
||||
install: npm install
|
178
modules/default/calendar/vendor/ical.js/LICENSE
vendored
178
modules/default/calendar/vendor/ical.js/LICENSE
vendored
@ -1,178 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
13
modules/default/calendar/vendor/ical.js/NOTICE
vendored
13
modules/default/calendar/vendor/ical.js/NOTICE
vendored
@ -1,13 +0,0 @@
|
||||
Copyright 2012 Peter Braden
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const ical = require('ical');
|
||||
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
|
||||
ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, function (err, data) {
|
||||
for (let k in data) {
|
||||
if (data.hasOwnProperty(k)) {
|
||||
var ev = data[k];
|
||||
if (data[k].type == 'VEVENT') {
|
||||
console.log(`${ev.summary} is in ${ev.location} on the ${ev.start.getDate()} of ${months[ev.start.getMonth()]} at ${ev.start.toLocaleTimeString('en-GB')}`);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
@ -1,118 +0,0 @@
|
||||
var ical = require('./node-ical')
|
||||
var moment = require('moment')
|
||||
|
||||
var data = ical.parseFile('./examples/example_rrule.ics');
|
||||
|
||||
// Complicated example demonstrating how to handle recurrence rules and exceptions.
|
||||
|
||||
for (var k in data) {
|
||||
|
||||
// When dealing with calendar recurrences, you need a range of dates to query against,
|
||||
// because otherwise you can get an infinite number of calendar events.
|
||||
var rangeStart = moment("2017-01-01");
|
||||
var rangeEnd = moment("2017-12-31");
|
||||
|
||||
|
||||
var event = data[k]
|
||||
if (event.type === 'VEVENT') {
|
||||
|
||||
var title = event.summary;
|
||||
var startDate = moment(event.start);
|
||||
var endDate = moment(event.end);
|
||||
|
||||
// Calculate the duration of the event for use with recurring events.
|
||||
var duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x"));
|
||||
|
||||
// Simple case - no recurrences, just print out the calendar event.
|
||||
if (typeof event.rrule === 'undefined')
|
||||
{
|
||||
console.log('title:' + title);
|
||||
console.log('startDate:' + startDate.format('MMMM Do YYYY, h:mm:ss a'));
|
||||
console.log('endDate:' + endDate.format('MMMM Do YYYY, h:mm:ss a'));
|
||||
console.log('duration:' + moment.duration(duration).humanize());
|
||||
console.log();
|
||||
}
|
||||
|
||||
// Complicated case - if an RRULE exists, handle multiple recurrences of the event.
|
||||
else if (typeof event.rrule !== 'undefined')
|
||||
{
|
||||
// For recurring events, get the set of event start dates that fall within the range
|
||||
// of dates we're looking for.
|
||||
var dates = event.rrule.between(
|
||||
rangeStart.toDate(),
|
||||
rangeEnd.toDate(),
|
||||
true,
|
||||
function(date, i) {return true;}
|
||||
)
|
||||
|
||||
// The "dates" array contains the set of dates within our desired date range range that are valid
|
||||
// for the recurrence rule. *However*, it's possible for us to have a specific recurrence that
|
||||
// had its date changed from outside the range to inside the range. One way to handle this is
|
||||
// to add *all* recurrence override entries into the set of dates that we check, and then later
|
||||
// filter out any recurrences that don't actually belong within our range.
|
||||
if (event.recurrences != undefined)
|
||||
{
|
||||
for (var r in event.recurrences)
|
||||
{
|
||||
// Only add dates that weren't already in the range we added from the rrule so that
|
||||
// we don't double-add those events.
|
||||
if (moment(new Date(r)).isBetween(rangeStart, rangeEnd) != true)
|
||||
{
|
||||
dates.push(new Date(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through the set of date entries to see which recurrences should be printed.
|
||||
for(var i in dates) {
|
||||
|
||||
var date = dates[i];
|
||||
var curEvent = event;
|
||||
var showRecurrence = true;
|
||||
var curDuration = duration;
|
||||
|
||||
startDate = moment(date);
|
||||
|
||||
// Use just the date of the recurrence to look up overrides and exceptions (i.e. chop off time information)
|
||||
var dateLookupKey = date.toISOString().substring(0, 10);
|
||||
|
||||
// For each date that we're checking, it's possible that there is a recurrence override for that one day.
|
||||
if ((curEvent.recurrences != undefined) && (curEvent.recurrences[dateLookupKey] != undefined))
|
||||
{
|
||||
// We found an override, so for this recurrence, use a potentially different title, start date, and duration.
|
||||
curEvent = curEvent.recurrences[dateLookupKey];
|
||||
startDate = moment(curEvent.start);
|
||||
curDuration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x"));
|
||||
}
|
||||
// If there's no recurrence override, check for an exception date. Exception dates represent exceptions to the rule.
|
||||
else if ((curEvent.exdate != undefined) && (curEvent.exdate[dateLookupKey] != undefined))
|
||||
{
|
||||
// This date is an exception date, which means we should skip it in the recurrence pattern.
|
||||
showRecurrence = false;
|
||||
}
|
||||
|
||||
// Set the the title and the end date from either the regular event or the recurrence override.
|
||||
var recurrenceTitle = curEvent.summary;
|
||||
endDate = moment(parseInt(startDate.format("x")) + curDuration, 'x');
|
||||
|
||||
// If this recurrence ends before the start of the date range, or starts after the end of the date range,
|
||||
// don't process it.
|
||||
if (endDate.isBefore(rangeStart) || startDate.isAfter(rangeEnd)) {
|
||||
showRecurrence = false;
|
||||
}
|
||||
|
||||
if (showRecurrence === true) {
|
||||
|
||||
console.log('title:' + recurrenceTitle);
|
||||
console.log('startDate:' + startDate.format('MMMM Do YYYY, h:mm:ss a'));
|
||||
console.log('endDate:' + endDate.format('MMMM Do YYYY, h:mm:ss a'));
|
||||
console.log('duration:' + moment.duration(curDuration).humanize());
|
||||
console.log();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-CALNAME:ical
|
||||
X-WR-TIMEZONE:US/Central
|
||||
X-WR-CALDESC:
|
||||
BEGIN:VEVENT
|
||||
UID:98765432-ABCD-DCBB-999A-987765432123
|
||||
DTSTART;TZID=US/Central:20170601T090000
|
||||
DTEND;TZID=US/Central:20170601T170000
|
||||
DTSTAMP:20170727T044436Z
|
||||
EXDATE;TZID=US/Central:20170706T090000,20170713T090000,20170720T090000,20
|
||||
170803T090000
|
||||
LAST-MODIFIED:20170727T044435Z
|
||||
RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20170814T045959Z;BYDAY=TH
|
||||
SEQUENCE:0
|
||||
SUMMARY:Recurring weekly meeting from June 1 - Aug 14 (except July 6, July 13, July 20, Aug 3)
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:98765432-ABCD-DCBB-999A-987765432123
|
||||
RECURRENCE-ID;TZID=US/Central:20170629T090000
|
||||
DTSTART;TZID=US/Central:20170703T090000
|
||||
DTEND;TZID=US/Central:20170703T120000
|
||||
DTSTAMP:20170727T044436Z
|
||||
LAST-MODIFIED:20170216T143445Z
|
||||
SEQUENCE:0
|
||||
SUMMARY:Last meeting in June moved to Monday July 3 and shortened to half day
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:12354454-ABCD-DCBB-999A-2349872354897
|
||||
DTSTART;TZID=US/Central:20171201T130000
|
||||
DTEND;TZID=US/Central:20171201T150000
|
||||
DTSTAMP:20170727T044436Z
|
||||
LAST-MODIFIED:20170727T044435Z
|
||||
SEQUENCE:0
|
||||
SUMMARY:Single event on Dec 1
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
452
modules/default/calendar/vendor/ical.js/ical.js
vendored
452
modules/default/calendar/vendor/ical.js/ical.js
vendored
@ -1,452 +0,0 @@
|
||||
(function(name, definition) {
|
||||
|
||||
/****************
|
||||
* A tolerant, minimal icalendar parser
|
||||
* (http://tools.ietf.org/html/rfc5545)
|
||||
*
|
||||
* <peterbraden@peterbraden.co.uk>
|
||||
* **************/
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = definition();
|
||||
} else if (typeof define === 'function' && typeof define.amd === 'object'){
|
||||
define(definition);
|
||||
} else {
|
||||
this[name] = definition();
|
||||
}
|
||||
|
||||
}('ical', function(){
|
||||
|
||||
// Unescape Text re RFC 4.3.11
|
||||
var text = function(t){
|
||||
t = t || "";
|
||||
return (t
|
||||
.replace(/\\\,/g, ',')
|
||||
.replace(/\\\;/g, ';')
|
||||
.replace(/\\[nN]/g, '\n')
|
||||
.replace(/\\\\/g, '\\')
|
||||
)
|
||||
}
|
||||
|
||||
var parseParams = function(p){
|
||||
var out = {}
|
||||
for (var i = 0; i<p.length; i++){
|
||||
if (p[i].indexOf('=') > -1){
|
||||
var segs = p[i].split('=');
|
||||
|
||||
out[segs[0]] = parseValue(segs.slice(1).join('='));
|
||||
|
||||
}
|
||||
}
|
||||
return out || sp
|
||||
}
|
||||
|
||||
var parseValue = function(val){
|
||||
if ('TRUE' === val)
|
||||
return true;
|
||||
|
||||
if ('FALSE' === val)
|
||||
return false;
|
||||
|
||||
var number = Number(val);
|
||||
if (!isNaN(number))
|
||||
return number;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
var storeValParam = function (name) {
|
||||
return function (val, curr) {
|
||||
var current = curr[name];
|
||||
if (Array.isArray(current)) {
|
||||
current.push(val);
|
||||
return curr;
|
||||
}
|
||||
|
||||
if (current != null) {
|
||||
curr[name] = [current, val];
|
||||
return curr;
|
||||
}
|
||||
|
||||
curr[name] = val;
|
||||
return curr
|
||||
}
|
||||
}
|
||||
|
||||
var storeParam = function (name) {
|
||||
return function (val, params, curr) {
|
||||
var data;
|
||||
if (params && params.length && !(params.length == 1 && params[0] === 'CHARSET=utf-8')) {
|
||||
data = { params: parseParams(params), val: text(val) }
|
||||
}
|
||||
else
|
||||
data = text(val)
|
||||
|
||||
return storeValParam(name)(data, curr);
|
||||
}
|
||||
}
|
||||
|
||||
var addTZ = function (dt, params) {
|
||||
var p = parseParams(params);
|
||||
|
||||
if (params && p){
|
||||
dt.tz = p.TZID
|
||||
}
|
||||
|
||||
return dt
|
||||
}
|
||||
|
||||
var dateParam = function(name){
|
||||
return function (val, params, curr) {
|
||||
|
||||
var newDate = text(val);
|
||||
|
||||
|
||||
if (params && params[0] === "VALUE=DATE") {
|
||||
// Just Date
|
||||
|
||||
var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(val);
|
||||
if (comps !== null) {
|
||||
// No TZ info - assume same timezone as this computer
|
||||
newDate = new Date(
|
||||
comps[1],
|
||||
parseInt(comps[2], 10)-1,
|
||||
comps[3]
|
||||
);
|
||||
|
||||
newDate = addTZ(newDate, params);
|
||||
newDate.dateOnly = true;
|
||||
|
||||
// Store as string - worst case scenario
|
||||
return storeValParam(name)(newDate, curr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//typical RFC date-time format
|
||||
var comps = /^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(Z)?$/.exec(val);
|
||||
if (comps !== null) {
|
||||
if (comps[7] == 'Z'){ // GMT
|
||||
newDate = new Date(Date.UTC(
|
||||
parseInt(comps[1], 10),
|
||||
parseInt(comps[2], 10)-1,
|
||||
parseInt(comps[3], 10),
|
||||
parseInt(comps[4], 10),
|
||||
parseInt(comps[5], 10),
|
||||
parseInt(comps[6], 10 )
|
||||
));
|
||||
// TODO add tz
|
||||
} else {
|
||||
newDate = new Date(
|
||||
parseInt(comps[1], 10),
|
||||
parseInt(comps[2], 10)-1,
|
||||
parseInt(comps[3], 10),
|
||||
parseInt(comps[4], 10),
|
||||
parseInt(comps[5], 10),
|
||||
parseInt(comps[6], 10)
|
||||
);
|
||||
}
|
||||
|
||||
newDate = addTZ(newDate, params);
|
||||
}
|
||||
|
||||
|
||||
// Store as string - worst case scenario
|
||||
return storeValParam(name)(newDate, curr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var geoParam = function(name){
|
||||
return function(val, params, curr){
|
||||
storeParam(val, params, curr)
|
||||
var parts = val.split(';');
|
||||
curr[name] = {lat:Number(parts[0]), lon:Number(parts[1])};
|
||||
return curr
|
||||
}
|
||||
}
|
||||
|
||||
var categoriesParam = function (name) {
|
||||
var separatorPattern = /\s*,\s*/g;
|
||||
return function (val, params, curr) {
|
||||
storeParam(val, params, curr)
|
||||
if (curr[name] === undefined)
|
||||
curr[name] = val ? val.split(separatorPattern) : []
|
||||
else
|
||||
if (val)
|
||||
curr[name] = curr[name].concat(val.split(separatorPattern))
|
||||
return curr
|
||||
}
|
||||
}
|
||||
|
||||
// EXDATE is an entry that represents exceptions to a recurrence rule (ex: "repeat every day except on 7/4").
|
||||
// The EXDATE entry itself can also contain a comma-separated list, so we make sure to parse each date out separately.
|
||||
// There can also be more than one EXDATE entries in a calendar record.
|
||||
// Since there can be multiple dates, we create an array of them. The index into the array is the ISO string of the date itself, for ease of use.
|
||||
// i.e. You can check if ((curr.exdate != undefined) && (curr.exdate[date iso string] != undefined)) to see if a date is an exception.
|
||||
// NOTE: This specifically uses date only, and not time. This is to avoid a few problems:
|
||||
// 1. The ISO string with time wouldn't work for "floating dates" (dates without timezones).
|
||||
// ex: "20171225T060000" - this is supposed to mean 6 AM in whatever timezone you're currently in
|
||||
// 2. Daylight savings time potentially affects the time you would need to look up
|
||||
// 3. Some EXDATE entries in the wild seem to have times different from the recurrence rule, but are still excluded by calendar programs. Not sure how or why.
|
||||
// These would fail any sort of sane time lookup, because the time literally doesn't match the event. So we'll ignore time and just use date.
|
||||
// ex: DTSTART:20170814T140000Z
|
||||
// RRULE:FREQ=WEEKLY;WKST=SU;INTERVAL=2;BYDAY=MO,TU
|
||||
// EXDATE:20171219T060000
|
||||
// Even though "T060000" doesn't match or overlap "T1400000Z", it's still supposed to be excluded? Odd. :(
|
||||
// TODO: See if this causes any problems with events that recur multiple times a day.
|
||||
var exdateParam = function (name) {
|
||||
return function (val, params, curr) {
|
||||
var separatorPattern = /\s*,\s*/g;
|
||||
curr[name] = curr[name] || [];
|
||||
var dates = val ? val.split(separatorPattern) : [];
|
||||
dates.forEach(function (entry) {
|
||||
var exdate = new Array();
|
||||
dateParam(name)(entry, params, exdate);
|
||||
|
||||
if (exdate[name])
|
||||
{
|
||||
if (typeof exdate[name].toISOString === 'function') {
|
||||
curr[name][exdate[name].toISOString().substring(0, 10)] = exdate[name];
|
||||
} else {
|
||||
console.error("No toISOString function in exdate[name]", exdate[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
return curr;
|
||||
}
|
||||
}
|
||||
|
||||
// RECURRENCE-ID is the ID of a specific recurrence within a recurrence rule.
|
||||
// TODO: It's also possible for it to have a range, like "THISANDPRIOR", "THISANDFUTURE". This isn't currently handled.
|
||||
var recurrenceParam = function (name) {
|
||||
return dateParam(name);
|
||||
}
|
||||
|
||||
var addFBType = function (fb, params) {
|
||||
var p = parseParams(params);
|
||||
|
||||
if (params && p){
|
||||
fb.type = p.FBTYPE || "BUSY"
|
||||
}
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
var freebusyParam = function (name) {
|
||||
return function(val, params, curr){
|
||||
var fb = addFBType({}, params);
|
||||
curr[name] = curr[name] || []
|
||||
curr[name].push(fb);
|
||||
|
||||
storeParam(val, params, fb);
|
||||
|
||||
var parts = val.split('/');
|
||||
|
||||
['start', 'end'].forEach(function (name, index) {
|
||||
dateParam(name)(parts[index], params, fb);
|
||||
});
|
||||
|
||||
return curr;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
|
||||
objectHandlers : {
|
||||
'BEGIN' : function(component, params, curr, stack){
|
||||
stack.push(curr)
|
||||
|
||||
return {type:component, params:params}
|
||||
}
|
||||
|
||||
, 'END' : function(component, params, curr, stack){
|
||||
// prevents the need to search the root of the tree for the VCALENDAR object
|
||||
if (component === "VCALENDAR") {
|
||||
//scan all high level object in curr and drop all strings
|
||||
var key,
|
||||
obj;
|
||||
|
||||
for (key in curr) {
|
||||
if(curr.hasOwnProperty(key)) {
|
||||
obj = curr[key];
|
||||
if (typeof obj === 'string') {
|
||||
delete curr[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return curr
|
||||
}
|
||||
|
||||
var par = stack.pop()
|
||||
|
||||
if (curr.uid)
|
||||
{
|
||||
// If this is the first time we run into this UID, just save it.
|
||||
if (par[curr.uid] === undefined)
|
||||
{
|
||||
par[curr.uid] = curr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we have multiple ical entries with the same UID, it's either going to be a
|
||||
// modification to a recurrence (RECURRENCE-ID), and/or a significant modification
|
||||
// to the entry (SEQUENCE).
|
||||
|
||||
// TODO: Look into proper sequence logic.
|
||||
|
||||
if (curr.recurrenceid === undefined)
|
||||
{
|
||||
// If we have the same UID as an existing record, and it *isn't* a specific recurrence ID,
|
||||
// not quite sure what the correct behaviour should be. For now, just take the new information
|
||||
// and merge it with the old record by overwriting only the fields that appear in the new record.
|
||||
var key;
|
||||
for (key in curr) {
|
||||
par[curr.uid][key] = curr[key];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If we have recurrence-id entries, list them as an array of recurrences keyed off of recurrence-id.
|
||||
// To use - as you're running through the dates of an rrule, you can try looking it up in the recurrences
|
||||
// array. If it exists, then use the data from the calendar object in the recurrence instead of the parent
|
||||
// for that day.
|
||||
|
||||
// NOTE: Sometimes the RECURRENCE-ID record will show up *before* the record with the RRULE entry. In that
|
||||
// case, what happens is that the RECURRENCE-ID record ends up becoming both the parent record and an entry
|
||||
// in the recurrences array, and then when we process the RRULE entry later it overwrites the appropriate
|
||||
// fields in the parent record.
|
||||
|
||||
if (curr.recurrenceid != null)
|
||||
{
|
||||
|
||||
// TODO: Is there ever a case where we have to worry about overwriting an existing entry here?
|
||||
|
||||
// Create a copy of the current object to save in our recurrences array. (We *could* just do par = curr,
|
||||
// except for the case that we get the RECURRENCE-ID record before the RRULE record. In that case, we
|
||||
// would end up with a shared reference that would cause us to overwrite *both* records at the point
|
||||
// that we try and fix up the parent record.)
|
||||
var recurrenceObj = new Object();
|
||||
var key;
|
||||
for (key in curr) {
|
||||
recurrenceObj[key] = curr[key];
|
||||
}
|
||||
|
||||
if (recurrenceObj.recurrences != undefined) {
|
||||
delete recurrenceObj.recurrences;
|
||||
}
|
||||
|
||||
|
||||
// If we don't have an array to store recurrences in yet, create it.
|
||||
if (par[curr.uid].recurrences === undefined) {
|
||||
par[curr.uid].recurrences = new Array();
|
||||
}
|
||||
|
||||
// Save off our cloned recurrence object into the array, keyed by date but not time.
|
||||
// We key by date only to avoid timezone and "floating time" problems (where the time isn't associated with a timezone).
|
||||
// TODO: See if this causes a problem with events that have multiple recurrences per day.
|
||||
if (typeof curr.recurrenceid.toISOString === 'function') {
|
||||
par[curr.uid].recurrences[curr.recurrenceid.toISOString().substring(0,10)] = recurrenceObj;
|
||||
} else {
|
||||
console.error("No toISOString function in curr.recurrenceid", curr.recurrenceid);
|
||||
}
|
||||
}
|
||||
|
||||
// One more specific fix - in the case that an RRULE entry shows up after a RECURRENCE-ID entry,
|
||||
// let's make sure to clear the recurrenceid off the parent field.
|
||||
if ((par[curr.uid].rrule != undefined) && (par[curr.uid].recurrenceid != undefined))
|
||||
{
|
||||
delete par[curr.uid].recurrenceid;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
par[Math.random()*100000] = curr // Randomly assign ID : TODO - use true GUID
|
||||
|
||||
return par
|
||||
}
|
||||
|
||||
, 'SUMMARY' : storeParam('summary')
|
||||
, 'DESCRIPTION' : storeParam('description')
|
||||
, 'URL' : storeParam('url')
|
||||
, 'UID' : storeParam('uid')
|
||||
, 'LOCATION' : storeParam('location')
|
||||
, 'DTSTART' : dateParam('start')
|
||||
, 'DTEND' : dateParam('end')
|
||||
, 'EXDATE' : exdateParam('exdate')
|
||||
,' CLASS' : storeParam('class')
|
||||
, 'TRANSP' : storeParam('transparency')
|
||||
, 'GEO' : geoParam('geo')
|
||||
, 'PERCENT-COMPLETE': storeParam('completion')
|
||||
, 'COMPLETED': dateParam('completed')
|
||||
, 'CATEGORIES': categoriesParam('categories')
|
||||
, 'FREEBUSY': freebusyParam('freebusy')
|
||||
, 'DTSTAMP': dateParam('dtstamp')
|
||||
, 'CREATED': dateParam('created')
|
||||
, 'LAST-MODIFIED': dateParam('lastmodified')
|
||||
, 'RECURRENCE-ID': recurrenceParam('recurrenceid')
|
||||
|
||||
},
|
||||
|
||||
|
||||
handleObject : function(name, val, params, ctx, stack, line){
|
||||
var self = this
|
||||
|
||||
if(self.objectHandlers[name])
|
||||
return self.objectHandlers[name](val, params, ctx, stack, line)
|
||||
|
||||
//handling custom properties
|
||||
if(name.match(/X\-[\w\-]+/) && stack.length > 0) {
|
||||
//trimming the leading and perform storeParam
|
||||
name = name.substring(2);
|
||||
return (storeParam(name))(val, params, ctx, stack, line);
|
||||
}
|
||||
|
||||
return storeParam(name.toLowerCase())(val, params, ctx);
|
||||
},
|
||||
|
||||
|
||||
parseICS : function(str){
|
||||
var self = this
|
||||
var lines = str.split(/\r?\n/)
|
||||
var ctx = {}
|
||||
var stack = []
|
||||
|
||||
for (var i = 0, ii = lines.length, l = lines[0]; i<ii; i++, l=lines[i]){
|
||||
//Unfold : RFC#3.1
|
||||
while (lines[i+1] && /[ \t]/.test(lines[i+1][0])) {
|
||||
l += lines[i+1].slice(1)
|
||||
i += 1
|
||||
}
|
||||
|
||||
var kv = l.split(":")
|
||||
|
||||
if (kv.length < 2){
|
||||
// Invalid line - must have k&v
|
||||
continue;
|
||||
}
|
||||
|
||||
// Although the spec says that vals with colons should be quote wrapped
|
||||
// in practise nobody does, so we assume further colons are part of the
|
||||
// val
|
||||
var value = kv.slice(1).join(":")
|
||||
, kp = kv[0].split(";")
|
||||
, name = kp[0]
|
||||
, params = kp.slice(1)
|
||||
|
||||
ctx = self.handleObject(name, value, params, ctx, stack, l) || {}
|
||||
}
|
||||
|
||||
// type and params are added to the list of items, get rid of them.
|
||||
delete ctx.type
|
||||
delete ctx.params
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
}
|
||||
}))
|
@ -1,8 +0,0 @@
|
||||
module.exports = require('./ical')
|
||||
|
||||
var node = require('./node-ical')
|
||||
|
||||
// Copy node functions across to exports
|
||||
for (var i in node){
|
||||
module.exports[i] = node[i]
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
var ical = require('./ical')
|
||||
, request = require('request')
|
||||
, fs = require('fs')
|
||||
|
||||
exports.fromURL = function(url, opts, cb){
|
||||
if (!cb)
|
||||
return;
|
||||
request(url, opts, function(err, r, data){
|
||||
if (err)
|
||||
{
|
||||
return cb(err, null);
|
||||
}
|
||||
else if (r.statusCode != 200)
|
||||
{
|
||||
return cb(r.statusCode + ": " + r.statusMessage, null);
|
||||
}
|
||||
|
||||
cb(undefined, ical.parseICS(data));
|
||||
})
|
||||
}
|
||||
|
||||
exports.parseFile = function(filename){
|
||||
return ical.parseICS(fs.readFileSync(filename, 'utf8'))
|
||||
}
|
||||
|
||||
|
||||
var rrule = require('rrule').RRule
|
||||
|
||||
function getLocaleISOString(date) {
|
||||
var year = date.getFullYear().toString(10).padStart(4,'0');
|
||||
var month = (date.getMonth() + 1).toString(10).padStart(2,'0');
|
||||
var day = date.getDate().toString(10).padStart(2,'0');
|
||||
var hour = date.getHours().toString(10).padStart(2,'0');
|
||||
var minute = date.getMinutes().toString(10).padStart(2,'0');
|
||||
var second = date.getSeconds().toString(10).padStart(2,'0');
|
||||
|
||||
return `${year}${month}${day}T${hour}${minute}${second}Z`;
|
||||
}
|
||||
|
||||
ical.objectHandlers['RRULE'] = function(val, params, curr, stack, line){
|
||||
curr.rrule = line;
|
||||
return curr
|
||||
}
|
||||
var originalEnd = ical.objectHandlers['END'];
|
||||
ical.objectHandlers['END'] = function (val, params, curr, stack) {
|
||||
// Recurrence rules are only valid for VEVENT, VTODO, and VJOURNAL.
|
||||
// More specifically, we need to filter the VCALENDAR type because we might end up with a defined rrule
|
||||
// due to the subtypes.
|
||||
if ((val === "VEVENT") || (val === "VTODO") || (val === "VJOURNAL")) {
|
||||
if (curr.rrule) {
|
||||
var rule = curr.rrule.replace('RRULE:', '');
|
||||
if (rule.indexOf('DTSTART') === -1) {
|
||||
|
||||
if (curr.start.length === 8) {
|
||||
var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(curr.start);
|
||||
if (comps) {
|
||||
curr.start = new Date(comps[1], comps[2] - 1, comps[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (typeof curr.start.toISOString === 'function') {
|
||||
try {
|
||||
// kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time
|
||||
rule += ';DTSTART=' + getLocaleISOString(curr.start);
|
||||
} catch (error) {
|
||||
console.error("ERROR when trying to convert to ISOString", error);
|
||||
}
|
||||
} else {
|
||||
console.error("No toISOString function in curr.start", curr.start);
|
||||
}
|
||||
}
|
||||
curr.rrule = rrule.fromString(rule);
|
||||
}
|
||||
}
|
||||
return originalEnd.call(this, val, params, curr, stack);
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
"name": "ical",
|
||||
"version": "0.5.0",
|
||||
"main": "index.js",
|
||||
"description": "A tolerant, minimal icalendar parser",
|
||||
"keywords": [
|
||||
"ical",
|
||||
"ics",
|
||||
"calendar"
|
||||
],
|
||||
"homepage": "https://github.com/peterbraden/ical.js",
|
||||
"author": "Peter Braden <peterbraden@peterbraden.co.uk> (peterbraden.co.uk)",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/peterbraden/ical.js.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"request": "^2.88.0",
|
||||
"rrule": "2.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vows": "0.8.2",
|
||||
"underscore": "1.9.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "./node_modules/vows/bin/vows ./test/test.js"
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
# ical.js #
|
||||
(Formerly node-ical)
|
||||
|
||||
[](https://travis-ci.org/peterbraden/ical.js)
|
||||
|
||||
A tolerant, minimal icalendar parser for javascript/node
|
||||
(http://tools.ietf.org/html/rfc5545)
|
||||
|
||||
|
||||
|
||||
## Install - Node.js ##
|
||||
|
||||
ical.js is availble on npm:
|
||||
|
||||
npm install ical
|
||||
|
||||
|
||||
|
||||
## API ##
|
||||
|
||||
ical.parseICS(str)
|
||||
|
||||
Parses a string with an ICS File
|
||||
|
||||
var data = ical.parseFile(filename)
|
||||
|
||||
Reads in the specified iCal file, parses it and returns the parsed data
|
||||
|
||||
ical.fromURL(url, options, function(err, data) {} )
|
||||
|
||||
Use the request library to fetch the specified URL (```opts``` gets passed on to the ```request()``` call), and call the function with the result (either an error or the data).
|
||||
|
||||
|
||||
|
||||
## Example 1 - Print list of upcoming node conferences (see example.js)
|
||||
```javascript
|
||||
'use strict';
|
||||
|
||||
const ical = require('ical');
|
||||
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
|
||||
ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics', {}, function (err, data) {
|
||||
for (let k in data) {
|
||||
if (data.hasOwnProperty(k)) {
|
||||
var ev = data[k];
|
||||
if (data[k].type == 'VEVENT') {
|
||||
console.log(`${ev.summary} is in ${ev.location} on the ${ev.start.getDate()} of ${months[ev.start.getMonth()]} at ${ev.start.toLocaleTimeString('en-GB')}`);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Recurrences and Exceptions ##
|
||||
Calendar events with recurrence rules can be significantly more complicated to handle correctly. There are three parts to handling them:
|
||||
|
||||
1. rrule - the recurrence rule specifying the pattern of recurring dates and times for the event.
|
||||
2. recurrences - an optional array of event data that can override specific occurrences of the event.
|
||||
3. exdate - an optional array of dates that should be excluded from the recurrence pattern.
|
||||
|
||||
See example_rrule.js for an example of handling recurring calendar events.
|
500
modules/default/calendar/vendor/ical.js/test/test.js
vendored
500
modules/default/calendar/vendor/ical.js/test/test.js
vendored
@ -1,500 +0,0 @@
|
||||
/****
|
||||
* Tests
|
||||
*
|
||||
*
|
||||
***/
|
||||
process.env.TZ = 'America/San_Francisco';
|
||||
var ical = require('../index')
|
||||
|
||||
var vows = require('vows')
|
||||
, assert = require('assert')
|
||||
, _ = require('underscore')
|
||||
|
||||
vows.describe('node-ical').addBatch({
|
||||
'when parsing test1.ics (node conferences schedule from lanyrd.com, modified)': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test1.ics')
|
||||
}
|
||||
|
||||
,'we get 9 events': function (topic) {
|
||||
var events = _.select(_.values(topic), function(x){ return x.type==='VEVENT'})
|
||||
assert.equal (events.length, 9);
|
||||
}
|
||||
|
||||
,'event 47f6e' : {
|
||||
topic: function(events){
|
||||
return _.select(_.values(events),
|
||||
function(x){
|
||||
return x.uid ==='47f6ea3f28af2986a2192fa39a91fa7d60d26b76'})[0]
|
||||
}
|
||||
,'is in fort lauderdale' : function(topic){
|
||||
assert.equal(topic.location, "Fort Lauderdale, United States")
|
||||
}
|
||||
,'starts Tue, 29 Nov 2011' : function(topic){
|
||||
assert.equal(topic.start.toDateString(), new Date(2011,10,29).toDateString())
|
||||
}
|
||||
}
|
||||
, 'event 480a' : {
|
||||
topic: function(events){
|
||||
return _.select(_.values(events),
|
||||
function(x){
|
||||
return x.uid ==='480a3ad48af5ed8965241f14920f90524f533c18'})[0]
|
||||
}
|
||||
, 'has a summary (invalid colon handling tolerance)' : function(topic){
|
||||
assert.equal(topic.summary, '[Async]: Everything Express')
|
||||
}
|
||||
, 'has a date only start datetime' : function(topic){
|
||||
assert.equal(topic.start.dateOnly, true)
|
||||
}
|
||||
, 'has a date only end datetime' : function(topic){
|
||||
assert.equal(topic.end.dateOnly, true)
|
||||
}
|
||||
}
|
||||
, 'event d4c8' :{
|
||||
topic : function(events){
|
||||
return _.select(_.values(events),
|
||||
function(x){
|
||||
return x.uid === 'd4c826dfb701f611416d69b4df81caf9ff80b03a'})[0]
|
||||
}
|
||||
, 'has a start datetime' : function(topic){
|
||||
assert.equal(topic.start.toDateString(), new Date(Date.UTC(2011, 2, 12, 20, 0, 0)).toDateString())
|
||||
}
|
||||
}
|
||||
|
||||
, 'event sdfkf09fsd0 (Invalid Date)' :{
|
||||
topic : function(events){
|
||||
return _.select(_.values(events),
|
||||
function(x){
|
||||
return x.uid === 'sdfkf09fsd0'})[0]
|
||||
}
|
||||
, 'has a start datetime' : function(topic){
|
||||
assert.equal(topic.start, "Next Year")
|
||||
}
|
||||
}
|
||||
}
|
||||
, 'with test2.ics (testing ical features)' : {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test2.ics')
|
||||
}
|
||||
, 'todo item uid4@host1.com' : {
|
||||
topic : function(items){
|
||||
return items['uid4@host1.com']
|
||||
}
|
||||
, 'is a VTODO' : function(topic){
|
||||
assert.equal(topic.type, 'VTODO')
|
||||
}
|
||||
}
|
||||
, 'vfreebusy' : {
|
||||
topic: function(events) {
|
||||
return _.select(_.values(events), function(x) {
|
||||
return x.type === 'VFREEBUSY';
|
||||
})[0];
|
||||
}
|
||||
, 'has a URL' : function(topic) {
|
||||
assert.equal(topic.url, 'http://www.host.com/calendar/busytime/jsmith.ifb');
|
||||
}
|
||||
}
|
||||
, 'vfreebusy first freebusy' : {
|
||||
topic: function(events) {
|
||||
return _.select(_.values(events), function(x) {
|
||||
return x.type === 'VFREEBUSY';
|
||||
})[0].freebusy[0];
|
||||
}
|
||||
, 'has undefined type defaulting to busy' : function(topic) {
|
||||
assert.equal(topic.type, "BUSY");
|
||||
}
|
||||
, 'has an start datetime' : function(topic) {
|
||||
assert.equal(topic.start.getFullYear(), 1998);
|
||||
assert.equal(topic.start.getUTCMonth(), 2);
|
||||
assert.equal(topic.start.getUTCDate(), 14);
|
||||
assert.equal(topic.start.getUTCHours(), 23);
|
||||
assert.equal(topic.start.getUTCMinutes(), 30);
|
||||
}
|
||||
, 'has an end datetime' : function(topic) {
|
||||
assert.equal(topic.end.getFullYear(), 1998);
|
||||
assert.equal(topic.end.getUTCMonth(), 2);
|
||||
assert.equal(topic.end.getUTCDate(), 15);
|
||||
assert.equal(topic.end.getUTCHours(), 00);
|
||||
assert.equal(topic.end.getUTCMinutes(), 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
, 'with test3.ics (testing tvcountdown.com)' : {
|
||||
topic: function() {
|
||||
return ical.parseFile('./test/test3.ics');
|
||||
}
|
||||
, 'event -83' : {
|
||||
topic: function(events) {
|
||||
return _.select(_.values(events), function(x) {
|
||||
return x.uid === '20110505T220000Z-83@tvcountdown.com';
|
||||
})[0];
|
||||
}
|
||||
, 'has a start datetime' : function(topic) {
|
||||
assert.equal(topic.start.getFullYear(), 2011);
|
||||
assert.equal(topic.start.getMonth(), 4);
|
||||
}
|
||||
, 'has an end datetime' : function(topic) {
|
||||
assert.equal(topic.end.getFullYear(), 2011);
|
||||
assert.equal(topic.end.getMonth(), 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
, 'with test4.ics (testing tripit.com)' : {
|
||||
topic: function() {
|
||||
return ical.parseFile('./test/test4.ics');
|
||||
}
|
||||
, 'event c32a5...' : {
|
||||
topic: function(events) {
|
||||
return _.select(_.values(events), function(x) {
|
||||
return x.uid === 'c32a5eaba2354bb29e012ec18da827db90550a3b@tripit.com';
|
||||
})[0];
|
||||
}
|
||||
, 'has a start datetime' : function(topic) {
|
||||
assert.equal(topic.start.getFullYear(), 2011);
|
||||
assert.equal(topic.start.getMonth(), 09);
|
||||
assert.equal(topic.start.getDate(), 11);
|
||||
}
|
||||
|
||||
, 'has a summary' : function(topic){
|
||||
// escaped commas and semicolons should be replaced
|
||||
assert.equal(topic.summary, 'South San Francisco, CA, October 2011;')
|
||||
|
||||
}
|
||||
|
||||
, 'has a description' : function(topic){
|
||||
var desired = 'John Doe is in South San Francisco, CA from Oct 11 ' +
|
||||
'to Oct 13, 2011\nView and/or edit details in TripIt : http://www.tripit.c' +
|
||||
'om/trip/show/id/23710889\nTripIt - organize your travel at http://www.trip' +
|
||||
'it.com\n'
|
||||
assert.equal(topic.description, desired)
|
||||
|
||||
}
|
||||
|
||||
, 'has a geolocation' : function(topic){
|
||||
assert.ok(topic.geo, 'no geo param')
|
||||
assert.equal(topic.geo.lat, 37.654656)
|
||||
assert.equal(topic.geo.lon, -122.40775)
|
||||
}
|
||||
|
||||
, 'has transparency' : function(topic){
|
||||
assert.equal(topic.transparency, 'TRANSPARENT')
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
, 'with test5.ics (testing meetup.com)' : {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test5.ics')
|
||||
}
|
||||
, 'event nsmxnyppbfc@meetup.com' : {
|
||||
topic: function(events) {
|
||||
return _.select(_.values(events), function(x) {
|
||||
return x.uid === 'event_nsmxnyppbfc@meetup.com';
|
||||
})[0];
|
||||
}
|
||||
, 'has a start' : function(topic){
|
||||
assert.equal(topic.start.tz, 'America/Phoenix')
|
||||
assert.equal(topic.start.toISOString(), new Date(2011, 10, 09, 19, 0,0).toISOString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
, 'with test6.ics (testing assembly.org)': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test6.ics')
|
||||
}
|
||||
, 'event with no ID' : {
|
||||
topic: function(events) {
|
||||
return _.select(_.values(events), function(x) {
|
||||
return x.summary === 'foobar Summer 2011 starts!';
|
||||
})[0];
|
||||
}
|
||||
, 'has a start' : function(topic){
|
||||
assert.equal(topic.start.toISOString(), new Date(2011, 07, 04, 12, 0,0).toISOString())
|
||||
}
|
||||
}
|
||||
, 'event with rrule' :{
|
||||
topic: function(events){
|
||||
return _.select(_.values(events), function(x){
|
||||
return x.summary === "foobarTV broadcast starts"
|
||||
})[0];
|
||||
}
|
||||
, "Has an RRULE": function(topic){
|
||||
assert.notEqual(topic.rrule, undefined);
|
||||
}
|
||||
, "RRule text": function(topic){
|
||||
assert.equal(topic.rrule.toText(), "every 5 weeks on Monday, Friday until January 30, 2013")
|
||||
}
|
||||
}
|
||||
}
|
||||
, 'with test7.ics (testing dtstart of rrule)' :{
|
||||
topic: function() {
|
||||
return ical.parseFile('./test/test7.ics');
|
||||
},
|
||||
'recurring yearly event (14 july)': {
|
||||
topic: function(events){
|
||||
var ev = _.values(events)[0];
|
||||
return ev.rrule.between(new Date(2013, 0, 1), new Date(2014, 0, 1));
|
||||
},
|
||||
'dt start well set': function(topic) {
|
||||
assert.equal(topic[0].toDateString(), new Date(2013, 6, 14).toDateString());
|
||||
}
|
||||
}
|
||||
}
|
||||
, "with test 8.ics (VTODO completion)": {
|
||||
topic: function() {
|
||||
return ical.parseFile('./test/test8.ics');
|
||||
},
|
||||
'grabbing VTODO task': {
|
||||
topic: function(topic) {
|
||||
return _.values(topic)[0];
|
||||
},
|
||||
'task completed': function(task){
|
||||
assert.equal(task.completion, 100);
|
||||
assert.equal(task.completed.toISOString(), new Date(2013, 06, 16, 10, 57, 45).toISOString());
|
||||
}
|
||||
}
|
||||
}
|
||||
, "with test 9.ics (VEVENT with VALARM)": {
|
||||
topic: function() {
|
||||
return ical.parseFile('./test/test9.ics');
|
||||
},
|
||||
'grabbing VEVENT task': {
|
||||
topic: function(topic) {
|
||||
return _.values(topic)[0];
|
||||
},
|
||||
'task completed': function(task){
|
||||
assert.equal(task.summary, "Event with an alarm");
|
||||
}
|
||||
}
|
||||
}
|
||||
, 'with test 11.ics (VEVENT with custom properties)': {
|
||||
topic: function() {
|
||||
return ical.parseFile('./test10.ics');
|
||||
},
|
||||
'grabbing custom properties': {
|
||||
topic: function(topic) {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'with test10.ics': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test10.ics');
|
||||
},
|
||||
|
||||
'when categories present': {
|
||||
topic: function (t) {return _.values(t)[0]},
|
||||
|
||||
'should be a list': function (e) {
|
||||
assert(e.categories instanceof [].constructor);
|
||||
},
|
||||
|
||||
'should contain individual category values': function (e) {
|
||||
assert.deepEqual(e.categories, ['cat1', 'cat2', 'cat3']);
|
||||
}
|
||||
},
|
||||
|
||||
'when categories present with trailing whitespace': {
|
||||
topic: function (t) {return _.values(t)[1]},
|
||||
|
||||
'should contain individual category values without whitespace': function (e) {
|
||||
assert.deepEqual(e.categories, ['cat1', 'cat2', 'cat3']);
|
||||
}
|
||||
},
|
||||
|
||||
'when categories present but empty': {
|
||||
topic: function (t) {return _.values(t)[2]},
|
||||
|
||||
'should be an empty list': function (e) {
|
||||
assert.deepEqual(e.categories, []);
|
||||
}
|
||||
},
|
||||
|
||||
'when categories present but singular': {
|
||||
topic: function (t) {return _.values(t)[3]},
|
||||
|
||||
'should be a list of single item': function (e) {
|
||||
assert.deepEqual(e.categories, ['lonely-cat']);
|
||||
}
|
||||
},
|
||||
|
||||
'when categories present on multiple lines': {
|
||||
topic: function (t) {return _.values(t)[4]},
|
||||
|
||||
'should contain the category values in an array': function (e) {
|
||||
assert.deepEqual(e.categories, ['cat1', 'cat2', 'cat3']);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'with test11.ics (testing zimbra freebusy)': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test11.ics');
|
||||
},
|
||||
|
||||
'freebusy params' : {
|
||||
topic: function(events) {
|
||||
return _.values(events)[0];
|
||||
}
|
||||
, 'has a URL' : function(topic) {
|
||||
assert.equal(topic.url, 'http://mail.example.com/yvr-2a@example.com/20140416');
|
||||
}
|
||||
, 'has an ORGANIZER' : function(topic) {
|
||||
assert.equal(topic.organizer, 'mailto:yvr-2a@example.com');
|
||||
}
|
||||
, 'has an start datetime' : function(topic) {
|
||||
assert.equal(topic.start.getFullYear(), 2014);
|
||||
assert.equal(topic.start.getMonth(), 3);
|
||||
}
|
||||
, 'has an end datetime' : function(topic) {
|
||||
assert.equal(topic.end.getFullYear(), 2014);
|
||||
assert.equal(topic.end.getMonth(), 6);
|
||||
}
|
||||
}
|
||||
, 'freebusy busy events' : {
|
||||
topic: function(events) {
|
||||
return _.select(_.values(events)[0].freebusy, function(x) {
|
||||
return x.type === 'BUSY';
|
||||
})[0];
|
||||
}
|
||||
, 'has an start datetime' : function(topic) {
|
||||
assert.equal(topic.start.getFullYear(), 2014);
|
||||
assert.equal(topic.start.getMonth(), 3);
|
||||
assert.equal(topic.start.getUTCHours(), 15);
|
||||
assert.equal(topic.start.getUTCMinutes(), 15);
|
||||
}
|
||||
, 'has an end datetime' : function(topic) {
|
||||
assert.equal(topic.end.getFullYear(), 2014);
|
||||
assert.equal(topic.end.getMonth(), 3);
|
||||
assert.equal(topic.end.getUTCHours(), 19);
|
||||
assert.equal(topic.end.getUTCMinutes(), 00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
, 'with test12.ics (testing recurrences and exdates)': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test12.ics')
|
||||
}
|
||||
, 'event with rrule': {
|
||||
topic: function (events) {
|
||||
return _.select(_.values(events), function (x) {
|
||||
return x.uid === '0000001';
|
||||
})[0];
|
||||
}
|
||||
, "Has an RRULE": function (topic) {
|
||||
assert.notEqual(topic.rrule, undefined);
|
||||
}
|
||||
, "Has summary Treasure Hunting": function (topic) {
|
||||
assert.equal(topic.summary, 'Treasure Hunting');
|
||||
}
|
||||
, "Has two EXDATES": function (topic) {
|
||||
assert.notEqual(topic.exdate, undefined);
|
||||
assert.notEqual(topic.exdate[new Date(2015, 06, 08, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
assert.notEqual(topic.exdate[new Date(2015, 06, 10, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
}
|
||||
, "Has a RECURRENCE-ID override": function (topic) {
|
||||
assert.notEqual(topic.recurrences, undefined);
|
||||
assert.notEqual(topic.recurrences[new Date(2015, 06, 07, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
assert.equal(topic.recurrences[new Date(2015, 06, 07, 12, 0, 0).toISOString().substring(0, 10)].summary, 'More Treasure Hunting');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
, 'with test13.ics (testing recurrence-id before rrule)': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test13.ics')
|
||||
}
|
||||
, 'event with rrule': {
|
||||
topic: function (events) {
|
||||
return _.select(_.values(events), function (x) {
|
||||
return x.uid === '6m2q7kb2l02798oagemrcgm6pk@google.com';
|
||||
})[0];
|
||||
}
|
||||
, "Has an RRULE": function (topic) {
|
||||
assert.notEqual(topic.rrule, undefined);
|
||||
}
|
||||
, "Has summary 'repeated'": function (topic) {
|
||||
assert.equal(topic.summary, 'repeated');
|
||||
}
|
||||
, "Has a RECURRENCE-ID override": function (topic) {
|
||||
assert.notEqual(topic.recurrences, undefined);
|
||||
assert.notEqual(topic.recurrences[new Date(2016, 7, 26, 14, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
assert.equal(topic.recurrences[new Date(2016, 7, 26, 14, 0, 0).toISOString().substring(0, 10)].summary, 'bla bla');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
, 'with test14.ics (testing comma-separated exdates)': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test14.ics')
|
||||
}
|
||||
, 'event with comma-separated exdate': {
|
||||
topic: function (events) {
|
||||
return _.select(_.values(events), function (x) {
|
||||
return x.uid === '98765432-ABCD-DCBB-999A-987765432123';
|
||||
})[0];
|
||||
}
|
||||
, "Has summary 'Example of comma-separated exdates'": function (topic) {
|
||||
assert.equal(topic.summary, 'Example of comma-separated exdates');
|
||||
}
|
||||
, "Has four comma-separated EXDATES": function (topic) {
|
||||
assert.notEqual(topic.exdate, undefined);
|
||||
// Verify the four comma-separated EXDATES are there
|
||||
assert.notEqual(topic.exdate[new Date(2017, 6, 6, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
assert.notEqual(topic.exdate[new Date(2017, 6, 17, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
assert.notEqual(topic.exdate[new Date(2017, 6, 20, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
assert.notEqual(topic.exdate[new Date(2017, 7, 3, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
// Verify an arbitrary date isn't there
|
||||
assert.equal(topic.exdate[new Date(2017, 4, 5, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
, 'with test14.ics (testing exdates with bad times)': {
|
||||
topic: function () {
|
||||
return ical.parseFile('./test/test14.ics')
|
||||
}
|
||||
, 'event with exdates with bad times': {
|
||||
topic: function (events) {
|
||||
return _.select(_.values(events), function (x) {
|
||||
return x.uid === '1234567-ABCD-ABCD-ABCD-123456789012';
|
||||
})[0];
|
||||
}
|
||||
, "Has summary 'Example of exdate with bad times'": function (topic) {
|
||||
assert.equal(topic.summary, 'Example of exdate with bad times');
|
||||
}
|
||||
, "Has two EXDATES even though they have bad times": function (topic) {
|
||||
assert.notEqual(topic.exdate, undefined);
|
||||
// Verify the two EXDATES are there, even though they have bad times
|
||||
assert.notEqual(topic.exdate[new Date(2017, 11, 18, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
assert.notEqual(topic.exdate[new Date(2017, 11, 19, 12, 0, 0).toISOString().substring(0, 10)], undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
, 'url request errors': {
|
||||
topic : function () {
|
||||
ical.fromURL('http://255.255.255.255/', {}, this.callback);
|
||||
}
|
||||
, 'are passed back to the callback' : function (err, result) {
|
||||
assert.instanceOf(err, Error);
|
||||
if (!err){
|
||||
console.log(">E:", err, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}).export(module)
|
||||
|
||||
|
||||
//ical.fromURL('http://lanyrd.com/topics/nodejs/nodejs.ics',
|
||||
// {},
|
||||
// function(err, data){
|
||||
// console.log("OUT:", data)
|
||||
// })
|
@ -1,78 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//lanyrd.com//Lanyrd//EN
|
||||
X-ORIGINAL-URL:http://lanyrd.com/topics/nodejs/nodejs.ics
|
||||
X-WR-CALNAME;CHARSET=utf-8:Node.js conferences
|
||||
VERSION:2.0
|
||||
METHOD:PUBLISH
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:Dyncon 2011
|
||||
LOCATION;CHARSET=utf-8:Stockholm, Sweden
|
||||
URL:http://lanyrd.com/2011/dyncon/
|
||||
UID:d4c826dfb701f611416d69b4df81caf9ff80b03a
|
||||
DTSTART:20110312T200000Z
|
||||
DTEND;VALUE=DATE:20110314
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:[Async]: Everything Express
|
||||
LOCATION;CHARSET=utf-8:Brighton, United Kingdom
|
||||
URL:http://lanyrd.com/2011/asyncjs-express/
|
||||
UID:480a3ad48af5ed8965241f14920f90524f533c18
|
||||
DTSTART;VALUE=DATE:20110324
|
||||
DTEND;VALUE=DATE:20110325
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:JSConf US 2011
|
||||
LOCATION;CHARSET=utf-8:Portland, United States
|
||||
URL:http://lanyrd.com/2011/jsconf/
|
||||
UID:ed334cc85db5ebdff5ff5a630a7a48631a677dbe
|
||||
DTSTART;VALUE=DATE:20110502
|
||||
DTEND;VALUE=DATE:20110504
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:NodeConf 2011
|
||||
LOCATION;CHARSET=utf-8:Portland, United States
|
||||
URL:http://lanyrd.com/2011/nodeconf/
|
||||
UID:25169a7b1ba5c248278f47120a40878055dc8c15
|
||||
DTSTART;VALUE=DATE:20110505
|
||||
DTEND;VALUE=DATE:20110506
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:BrazilJS
|
||||
LOCATION;CHARSET=utf-8:Fortaleza, Brazil
|
||||
URL:http://lanyrd.com/2011/braziljs/
|
||||
UID:dafee3be83624f3388c5635662229ff11766bb9c
|
||||
DTSTART;VALUE=DATE:20110513
|
||||
DTEND;VALUE=DATE:20110515
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:Falsy Values
|
||||
LOCATION;CHARSET=utf-8:Warsaw, Poland
|
||||
URL:http://lanyrd.com/2011/falsy-values/
|
||||
UID:73cad6a09ac4e7310979c6130f871d17d990b5ad
|
||||
DTSTART;VALUE=DATE:20110518
|
||||
DTEND;VALUE=DATE:20110521
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:nodecamp.eu
|
||||
LOCATION;CHARSET=utf-8:Cologne, Germany
|
||||
URL:http://lanyrd.com/2011/nodecampde/
|
||||
UID:b728a5fdb5f292b6293e4a2fd97a1ccfc69e9d6f
|
||||
DTSTART;VALUE=DATE:20110611
|
||||
DTEND;VALUE=DATE:20110613
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:Rich Web Experience 2011
|
||||
LOCATION;CHARSET=utf-8:Fort Lauderdale, United States
|
||||
URL:http://lanyrd.com/2011/rich-web-experience/
|
||||
UID:47f6ea3f28af2986a2192fa39a91fa7d60d26b76
|
||||
DTSTART;VALUE=DATE:20111129
|
||||
DTEND;VALUE=DATE:20111203
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY;CHARSET=utf-8:Foobar
|
||||
UID:sdfkf09fsd0
|
||||
DTSTART;VALUE=DATE:Next Year
|
||||
DTEND;VALUE=DATE:20111203
|
||||
END:VEVENT
|
||||
|
||||
END:VCALENDAR
|
@ -1,34 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:1
|
||||
SUMMARY:Event with a category
|
||||
DESCRIPTION:Details for an event with a category
|
||||
CATEGORIES:cat1,cat2,cat3
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:2
|
||||
SUMMARY:Event with a category
|
||||
DESCRIPTION:Details for an event with a category
|
||||
CATEGORIES:cat1 , cat2, cat3
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:3
|
||||
SUMMARY:Event with a category
|
||||
DESCRIPTION:Details for an event with a category
|
||||
CATEGORIES:
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:4
|
||||
SUMMARY:Event with a category
|
||||
DESCRIPTION:Details for an event with a category
|
||||
CATEGORIES:lonely-cat
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:5
|
||||
SUMMARY:Event with a category
|
||||
DESCRIPTION:Details for an event with a category
|
||||
CATEGORIES:cat1
|
||||
CATEGORIES:cat2
|
||||
CATEGORIES:cat3
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@ -1,41 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:Zimbra-Calendar-Provider
|
||||
VERSION:2.0
|
||||
METHOD:PUBLISH
|
||||
BEGIN:VFREEBUSY
|
||||
ORGANIZER:mailto:yvr-2a@example.com
|
||||
DTSTAMP:20140516T235436Z
|
||||
DTSTART:20140415T235436Z
|
||||
DTEND:20140717T235436Z
|
||||
URL:http://mail.example.com/yvr-2a@example.com/20140416
|
||||
FREEBUSY;FBTYPE=BUSY:20140416T151500Z/20140416T190000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140416T195500Z/20140416T231500Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140417T193000Z/20140417T203000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140421T210000Z/20140421T213000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140423T180000Z/20140423T190000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140423T200000Z/20140423T210000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140423T223500Z/20140423T231500Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140424T155000Z/20140424T165500Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140424T170000Z/20140424T183000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140424T195000Z/20140424T230000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140425T144500Z/20140425T161500Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140425T180000Z/20140425T194500Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140425T223000Z/20140425T230000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140428T151500Z/20140428T163000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140428T170000Z/20140428T173000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140428T195500Z/20140428T213000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140428T231000Z/20140428T234000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140429T152500Z/20140429T170000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140429T180000Z/20140429T183000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140429T201500Z/20140429T230000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140430T162500Z/20140430T165500Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140430T180000Z/20140430T190000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140501T170000Z/20140501T173000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140501T175000Z/20140501T190000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140501T232000Z/20140501T235000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140502T163500Z/20140502T173000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140505T165500Z/20140505T173000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140505T201500Z/20140505T203000Z
|
||||
FREEBUSY;FBTYPE=BUSY:20140505T210000Z/20140505T213000Z
|
||||
END:VFREEBUSY
|
||||
END:VCALENDAR
|
@ -1,19 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:0000001
|
||||
SUMMARY:Treasure Hunting
|
||||
DTSTART;TZID=America/Los_Angeles:20150706T120000
|
||||
DTEND;TZID=America/Los_Angeles:20150706T130000
|
||||
RRULE:FREQ=DAILY;COUNT=10
|
||||
EXDATE;TZID=America/Los_Angeles:20150708T120000
|
||||
EXDATE;TZID=America/Los_Angeles:20150710T120000
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:0000001
|
||||
SUMMARY:More Treasure Hunting
|
||||
LOCATION:The other island
|
||||
DTSTART;TZID=America/Los_Angeles:20150709T150000
|
||||
DTEND;TZID=America/Los_Angeles:20150707T160000
|
||||
RECURRENCE-ID;TZID=America/Los_Angeles:20150707T120000
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@ -1,57 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-CALNAME:ical
|
||||
X-WR-TIMEZONE:Europe/Kiev
|
||||
X-WR-CALDESC:
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:Europe/Kiev
|
||||
X-LIC-LOCATION:Europe/Kiev
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:+0200
|
||||
TZOFFSETTO:+0300
|
||||
TZNAME:EEST
|
||||
DTSTART:19700329T030000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:+0300
|
||||
TZOFFSETTO:+0200
|
||||
TZNAME:EET
|
||||
DTSTART:19701025T040000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=Europe/Kiev:20160826T140000
|
||||
DTEND;TZID=Europe/Kiev:20160826T150000
|
||||
DTSTAMP:20160825T061505Z
|
||||
UID:6m2q7kb2l02798oagemrcgm6pk@google.com
|
||||
RECURRENCE-ID;TZID=Europe/Kiev:20160826T140000
|
||||
CREATED:20160823T125221Z
|
||||
DESCRIPTION:
|
||||
LAST-MODIFIED:20160823T130320Z
|
||||
LOCATION:
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:bla bla
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=Europe/Kiev:20160825T140000
|
||||
DTEND;TZID=Europe/Kiev:20160825T150000
|
||||
RRULE:FREQ=DAILY;UNTIL=20160828T110000Z
|
||||
DTSTAMP:20160825T061505Z
|
||||
UID:6m2q7kb2l02798oagemrcgm6pk@google.com
|
||||
CREATED:20160823T125221Z
|
||||
DESCRIPTION:
|
||||
LAST-MODIFIED:20160823T125221Z
|
||||
LOCATION:
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:repeated
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@ -1,33 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-CALNAME:ical
|
||||
X-WR-TIMEZONE:Europe/Kiev
|
||||
X-WR-CALDESC:
|
||||
BEGIN:VEVENT
|
||||
UID:98765432-ABCD-DCBB-999A-987765432123
|
||||
DTSTART;TZID=US/Central:20170216T090000
|
||||
DTEND;TZID=US/Central:20170216T190000
|
||||
DTSTAMP:20170727T044436Z
|
||||
EXDATE;TZID=US/Central:20170706T090000,20170717T090000,20170720T090000,20
|
||||
170803T090000
|
||||
LAST-MODIFIED:20170727T044435Z
|
||||
RRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20170814T045959Z;INTERVAL=2;BYDAY=MO,TH
|
||||
SEQUENCE:0
|
||||
SUMMARY:Example of comma-separated exdates
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:1234567-ABCD-ABCD-ABCD-123456789012
|
||||
DTSTART:20170814T140000Z
|
||||
DTEND:20170815T000000Z
|
||||
DTSTAMP:20171204T134925Z
|
||||
EXDATE:20171219T060000
|
||||
EXDATE:20171218T060000
|
||||
LAST-MODIFIED:20171024T140004Z
|
||||
RRULE:FREQ=WEEKLY;WKST=SU;INTERVAL=2;BYDAY=MO,TU
|
||||
SEQUENCE:0
|
||||
SUMMARY:Example of exdate with bad times
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@ -1,83 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
CALSCALE:GREGORIAN
|
||||
X-WR-TIMEZONE;VALUE=TEXT:US/Pacific
|
||||
METHOD:PUBLISH
|
||||
PRODID:-//Apple Computer\, Inc//iCal 1.0//EN
|
||||
X-WR-CALNAME;VALUE=TEXT:Example
|
||||
VERSION:2.0
|
||||
BEGIN:VEVENT
|
||||
SEQUENCE:5
|
||||
DTSTART;TZID=US/Pacific:20021028T140000
|
||||
DTSTAMP:20021028T011706Z
|
||||
SUMMARY:Coffee with Jason
|
||||
UID:EC9439B1-FF65-11D6-9973-003065F99D04
|
||||
DTEND;TZID=US/Pacific:20021028T150000
|
||||
END:VEVENT
|
||||
BEGIN:VALARM
|
||||
TRIGGER;VALUE=DURATION:-P1D
|
||||
ACTION:DISPLAY
|
||||
DESCRIPTION:Event reminder
|
||||
END:VALARM
|
||||
BEGIN:VEVENT
|
||||
SEQUENCE:1
|
||||
DTSTAMP:20021128T012034Z
|
||||
SUMMARY:Code Review
|
||||
UID:EC944331-FF65-11D6-9973-003065F99D04
|
||||
DTSTART;TZID=US/Pacific:20021127T120000
|
||||
DURATION:PT1H
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SEQUENCE:1
|
||||
DTSTAMP:20021028T012034Z
|
||||
SUMMARY:Dinner with T
|
||||
UID:EC944CFA-FF65-11D6-9973-003065F99D04
|
||||
DTSTART;TZID=US/Pacific:20021216T200000
|
||||
DURATION:PT1H
|
||||
END:VEVENT
|
||||
BEGIN:VTODO
|
||||
DTSTAMP:19980130T134500Z
|
||||
SEQUENCE:2
|
||||
UID:uid4@host1.com
|
||||
ORGANIZER:MAILTO:unclesam@us.gov
|
||||
ATTENDEE;PARTSTAT=ACCEPTED:MAILTO:jqpublic@host.com
|
||||
DUE:19980415T235959
|
||||
STATUS:NEEDS-ACTION
|
||||
SUMMARY:Submit Income Taxes
|
||||
END:VTODO
|
||||
BEGIN:VALARM
|
||||
ACTION:AUDIO
|
||||
TRIGGER:19980403T120000
|
||||
ATTACH;FMTTYPE=audio/basic:http://host.com/pub/audio-
|
||||
files/ssbanner.aud
|
||||
REPEAT:4
|
||||
DURATION:PT1H
|
||||
END:VALARM
|
||||
BEGIN:VJOURNAL
|
||||
DTSTAMP:19970324T120000Z
|
||||
UID:uid5@host1.com
|
||||
ORGANIZER:MAILTO:jsmith@host.com
|
||||
STATUS:DRAFT
|
||||
CLASS:PUBLIC
|
||||
CATEGORY:Project Report, XYZ, Weekly Meeting
|
||||
DESCRIPTION:Project xyz Review Meeting Minutes\n
|
||||
Agenda\n1. Review of project version 1.0 requirements.\n2.
|
||||
Definition
|
||||
of project processes.\n3. Review of project schedule.\n
|
||||
Participants: John Smith, Jane Doe, Jim Dandy\n-It was
|
||||
decided that the requirements need to be signed off by
|
||||
product marketing.\n-Project processes were accepted.\n
|
||||
-Project schedule needs to account for scheduled holidays
|
||||
and employee vacation time. Check with HR for specific
|
||||
dates.\n-New schedule will be distributed by Friday.\n-
|
||||
Next weeks meeting is cancelled. No meeting until 3/23.
|
||||
END:VJOURNAL
|
||||
BEGIN:VFREEBUSY
|
||||
ORGANIZER:MAILTO:jsmith@host.com
|
||||
DTSTART:19980313T141711Z
|
||||
DTEND:19980410T141711Z
|
||||
FREEBUSY:19980314T233000Z/19980315T003000Z
|
||||
FREEBUSY:19980316T153000Z/19980316T163000Z
|
||||
FREEBUSY:19980318T030000Z/19980318T040000Z
|
||||
URL:http://www.host.com/calendar/busytime/jsmith.ifb
|
||||
END:VFREEBUSY
|
||||
END:VCALENDAR
|
@ -1,226 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
CALSCALE:GREGORIAN
|
||||
PRODID:tvcountdown.com
|
||||
X-WR-CALNAME:tvcountdown.com
|
||||
VERSION:2.0
|
||||
METHOD:PUBLISH
|
||||
X-WR-TIMEZONE:US/Eastern
|
||||
X-WR-CALNAME;VALUE=TEXT:tvcountdown.com
|
||||
X-WR-CALDESC:
|
||||
BEGIN:VEVENT
|
||||
UID:20110519T200000Z-79@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110519T200000
|
||||
DTEND;VALUE=DATE-TIME:20110519T203000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Big Bang Theory - S04E24 - The Roomate Transmogrfication
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110512T200000Z-79@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110512T200000
|
||||
DTEND;VALUE=DATE-TIME:20110512T203000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Big Bang Theory - S04E23 - The Engagement Reaction
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110505T220000Z-83@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110505T220000
|
||||
DTEND;VALUE=DATE-TIME:20110505T223000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:30 Rock - S05E23 - Respawn
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110505T200000Z-79@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110505T200000
|
||||
DTEND;VALUE=DATE-TIME:20110505T203000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Big Bang Theory - S04E22 - The Wildebeest Implementation
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110504T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110504T230000
|
||||
DTEND;VALUE=DATE-TIME:20110504T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E59 - David Barton
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110503T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110503T230000
|
||||
DTEND;VALUE=DATE-TIME:20110503T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E58 - Rachel Maddow
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110502T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110502T230000
|
||||
DTEND;VALUE=DATE-TIME:20110502T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E57 - Philip K. Howard
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110428T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110428T230000
|
||||
DTEND;VALUE=DATE-TIME:20110428T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E56 - William Cohan
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110428T220000Z-83@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110428T220000
|
||||
DTEND;VALUE=DATE-TIME:20110428T223000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:30 Rock - S05E22 - Everything Sunny All the Time Always
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110428T200000Z-79@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110428T200000
|
||||
DTEND;VALUE=DATE-TIME:20110428T203000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Big Bang Theory - S04E21 - The Agreement Dissection
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110427T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110427T230000
|
||||
DTEND;VALUE=DATE-TIME:20110427T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E55 - Sen. Bernie Sanders
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110426T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110426T230000
|
||||
DTEND;VALUE=DATE-TIME:20110426T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E54 - Elizabeth Warren
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110425T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110425T230000
|
||||
DTEND;VALUE=DATE-TIME:20110425T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E53 - Gigi Ibrahim
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110421T220000Z-83@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110421T220000
|
||||
DTEND;VALUE=DATE-TIME:20110421T223000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:30 Rock - S05E21 - 100th Episode Part 2 of 2
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110421T220000Z-83@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110421T220000
|
||||
DTEND;VALUE=DATE-TIME:20110421T223000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:30 Rock - S05E20 - 100th Episode Part 1 of 2
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110414T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110414T230000
|
||||
DTEND;VALUE=DATE-TIME:20110414T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E52 - Ricky Gervais
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110414T220000Z-83@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110414T220000
|
||||
DTEND;VALUE=DATE-TIME:20110414T223000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:30 Rock - S05E19 - I Heart Connecticut
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110413T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110413T230000
|
||||
DTEND;VALUE=DATE-TIME:20110413T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E51 - Tracy Morgan
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110412T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110412T230000
|
||||
DTEND;VALUE=DATE-TIME:20110412T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E50 - Gov. Deval Patrick
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110411T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110411T230000
|
||||
DTEND;VALUE=DATE-TIME:20110411T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E49 - Foo Fighters
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110407T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110407T230000
|
||||
DTEND;VALUE=DATE-TIME:20110407T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E48 - Jamie Oliver
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110407T200000Z-79@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110407T200000
|
||||
DTEND;VALUE=DATE-TIME:20110407T203000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Big Bang Theory - S04E20 - The Herb Garden Germination
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110406T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110406T230000
|
||||
DTEND;VALUE=DATE-TIME:20110406T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E47 - Mike Huckabee
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110405T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110405T230000
|
||||
DTEND;VALUE=DATE-TIME:20110405T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E46 - Colin Quinn
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110404T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110404T230000
|
||||
DTEND;VALUE=DATE-TIME:20110404T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E45 - Billy Crystal
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110331T230000Z-289@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110331T230000
|
||||
DTEND;VALUE=DATE-TIME:20110331T233000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Daily Show - S16E44 - Norm MacDonald
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
UID:20110331T200000Z-79@tvcountdown.com
|
||||
DTSTART;VALUE=DATE-TIME:20110331T200000
|
||||
DTEND;VALUE=DATE-TIME:20110331T203000
|
||||
DTSTAMP:20110430T192946Z
|
||||
URL;VALUE=URI:
|
||||
SUMMARY:The Big Bang Theory - S04E19 - The Zarnecki Incursion
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@ -1,747 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
X-WR-CALNAME:John Doe (TripIt)
|
||||
X-WR-CALDESC:TripIt Calendar
|
||||
X-PUBLISHED-TTL:PT15M
|
||||
PRODID:-//John Doe/NONSGML Bennu 0.1//EN
|
||||
VERSION:2.0
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
UID:c32a5eaba2354bb29e012ec18da827db90550a3b@tripit.com
|
||||
DTSTART;VALUE=DATE:20111011
|
||||
DTEND;VALUE=DATE:20111014
|
||||
SUMMARY:South San Francisco\, CA\, October 2011\;
|
||||
LOCATION:South San Francisco\, CA
|
||||
GEO:37.654656;-122.40775
|
||||
TRANSP:TRANSPARENT
|
||||
DESCRIPTION:John Doe is in South San Francisco\, CA from Oct 11
|
||||
to Oct 13\, 2011\nView and/or edit details in TripIt : http://www.tripit.c
|
||||
om/trip/show/id/23710889\nTripIt - organize your travel at http://www.trip
|
||||
it.com\n
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-ee275ccffa83f492d9eb63b01953b39f18d4f944@tripit.com
|
||||
DTSTART:20111011T100500
|
||||
DTEND:20111011T110500
|
||||
SUMMARY:Directions from SFO to Embassy Suites San Francisco Airport - Sout
|
||||
h San Francisco
|
||||
LOCATION:250 GATEWAY BLVD\, South San Francisco\, CA\, 94080
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/1234\n \n[Directions] 10/11/2011 10:05am - Directions from S
|
||||
FO to Embassy Suites San Francisco Airport - South San Francisco \nfrom: S
|
||||
FO \nto: 250 GATEWAY BLVD\, South San Francisco\, CA\, 94080 \nView direct
|
||||
ions here: http://maps.google.com/maps?output=mobile&saddr=SFO&daddr=250+G
|
||||
ATEWAY+BLVD%2C+South+San+Francisco%2C+CA%2C+94080 \n \n \n\nTripIt - organ
|
||||
ize your travel at http://www.tripit.com
|
||||
GEO:37.655634;-122.401273
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111011T165500Z
|
||||
SUMMARY:US403 PHX to SFO
|
||||
LOCATION:Phoenix (PHX)
|
||||
UID:item-c576afd397cf1f90578b4ba35e781b61ba8897db@tripit.com
|
||||
DTSTART:20111011T144500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/1234\n \n[Flight] 10/11/2011 US Airways(US) #403 dep PHX 7:4
|
||||
5am MST arr SFO 9:55am PDT\; John Doe\; seat(s) 8B\; conf #DXH9K
|
||||
Z\, BXQ9WH \nBooked on http://www.americanexpress-travel.com/\; Reference
|
||||
#: 4127 8626 9715\; http://www.americanexpress-travel.com/\; US:1-800-297-
|
||||
2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at htt
|
||||
p://www.tripit.com
|
||||
GEO:37.618889;-122.375
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Pick-up Rental Car: Dollar Rent A Car
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-e99a90ee1c7e4f5b68a4e551009e5bb6c475940c@tripit.com
|
||||
DTSTART:20111011T172500Z
|
||||
DTEND:20111011T182500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/1234\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte
|
||||
rnational Airport\; primary driver John Doe\; conf #R9508361 \np
|
||||
ickup 10/11/2011 10:25am\; dropoff 10/13/2011 6:49pm \nEconomy \nBooked on
|
||||
http://www.americanexpress-travel.com/\; Reference #: 4127 8626 9715\; ht
|
||||
tp://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582
|
||||
-2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-in: Embassy Suites San Francisco Airport - South San Francis
|
||||
co
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-7f3288d418bed063cc82b4512e792fbb5d8ae761@tripit.com
|
||||
DTSTART:20111011T185500Z
|
||||
DTEND:20111011T195500Z
|
||||
LOCATION:250 GATEWAY BLVD\, South San Francisco\, CA\, 94080
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/23710889\n \n[Lodging] Embassy Suites San Francisco Airport - So
|
||||
uth San Francisco\; primary guest John Doe\; conf #R9508361 \n25
|
||||
0 GATEWAY BLVD\, South San Francisco\, CA\, 94080\; tel 1.650.589.3400 \na
|
||||
rrive 10/11/2011\; depart 10/13/2011\; rooms: 1 \nBooked on http://www.ame
|
||||
ricanexpress-travel.com/\; Reference #: 4127 8626 9715\; http://www.americ
|
||||
anexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n \n \n\
|
||||
nTripIt - organize your travel at http://www.tripit.com
|
||||
GEO:37.655634;-122.401273
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-out: Embassy Suites San Francisco Airport - South San Franci
|
||||
sco
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-5eb4cb5fc25c55b0423921e18336e57f8c34598d@tripit.com
|
||||
DTSTART:20111014T011900Z
|
||||
DTEND:20111014T021900Z
|
||||
LOCATION:250 GATEWAY BLVD\, South San Francisco\, CA\, 94080
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/23710889\n \n[Lodging] Embassy Suites San Francisco Airport - So
|
||||
uth San Francisco\; primary guest John Doe\; conf #R9508361 \n25
|
||||
0 GATEWAY BLVD\, South San Francisco\, CA\, 94080\; tel 1.650.589.3400 \na
|
||||
rrive 10/11/2011\; depart 10/13/2011\; rooms: 1 \nBooked on http://www.ame
|
||||
ricanexpress-travel.com/\; Reference #: 4127 8626 9715\; http://www.americ
|
||||
anexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n \n \n\
|
||||
nTripIt - organize your travel at http://www.tripit.com
|
||||
GEO:37.655634;-122.401273
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Drop-off Rental Car: Dollar Rent A Car
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-11fdbf5d02e84646025716d9f9c7a4158e1fb025@tripit.com
|
||||
DTSTART:20111014T014900Z
|
||||
DTEND:20111014T024900Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/23710889\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte
|
||||
rnational Airport\; primary driver John Doe\; conf #R9508361 \np
|
||||
ickup 10/11/2011 10:25am\; dropoff 10/13/2011 6:49pm \nEconomy \nBooked on
|
||||
http://www.americanexpress-travel.com/\; Reference #: 4127 8626 9715\; ht
|
||||
tp://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582
|
||||
-2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111014T051900Z
|
||||
SUMMARY:CO6256 SFO to PHX
|
||||
LOCATION:San Francisco (SFO)
|
||||
UID:item-cb485a571a01972d6bdc74c2b829905d6e3786bf@tripit.com
|
||||
DTSTART:20111014T031900Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/23710889\n \n[Flight] 10/13/2011 Continental Airlines(CO) #6256
|
||||
dep SFO 8:19pm PDT arr PHX 10:19pm MST\; John Doe\; conf #DXH9KZ
|
||||
\, BXQ9WH(Operated by United Airlines flight 6256) \nBooked on http://www.
|
||||
americanexpress-travel.com/\; Reference #: 4127 8626 9715\; http://www.ame
|
||||
ricanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n \n
|
||||
\n\nTripIt - organize your travel at http://www.tripit.com
|
||||
GEO:33.436111;-112.009444
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
UID:c7b133db1e7be2713a4a63b75dcbad209690cab5@tripit.com
|
||||
DTSTART;VALUE=DATE:20111023
|
||||
DTEND;VALUE=DATE:20111028
|
||||
SUMMARY:Santa Barbara\, CA\, October 2011
|
||||
LOCATION:Santa Barbara\, CA
|
||||
GEO:34.420831;-119.69819
|
||||
TRANSP:TRANSPARENT
|
||||
DESCRIPTION:John Doe is in Santa Barbara\, CA from Oct 23 to Oct
|
||||
27\, 2011\nView and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\nTripIt - organize your travel at http://www.tripit.com
|
||||
\n
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111023T191200Z
|
||||
SUMMARY:US2719 PHX to SBA
|
||||
LOCATION:Phoenix (PHX)
|
||||
UID:item-c4375369e9070fcc04df39ed18c4d93087577591@tripit.com
|
||||
DTSTART:20111023T173500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Flight] 10/23/2011 US Airways(US) #2719 dep PHX 10
|
||||
:35am MST arr SBA 12:12pm PDT\; John Doe Ticket #0378717202638\;
|
||||
conf #A44XS5\, PRX98G\, FYYJZ4 \nBooked on http://www.americanexpress-tra
|
||||
vel.com/\; Reference #: 7128 8086 8504\; http://www.americanexpress-travel
|
||||
.com/\; US:1-800-297-2977\, Outside:210-582-2716\; Total Cost: $699.99 \n
|
||||
\n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
GEO:34.427778;-119.839444
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-962e4f045d12149319d1837ec096bf43770abd6e@tripit.com
|
||||
DTSTART:20111025T094000
|
||||
DTEND:20111025T104000
|
||||
SUMMARY:Directions from Hertz to Sofitel San Francisco Bay
|
||||
LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Directions] 10/25/2011 9:40am - Directions from He
|
||||
rtz to Sofitel San Francisco Bay \nfrom: 780 McDonnell Road\, San Francisc
|
||||
o\, CA\, 94128 \nto: 223 Twin Dolphin Drive\, Redwood City\, CA\, 94065 \n
|
||||
View directions here: http://maps.google.com/maps?output=mobile&saddr=780+
|
||||
McDonnell+Road%2C+San+Francisco%2C+CA%2C+94128&daddr=223+Twin+Dolphin+Driv
|
||||
e%2C+Redwood+City%2C+CA%2C+94065 \n \n \n\nTripIt - organize your travel a
|
||||
t http://www.tripit.com
|
||||
GEO:37.5232475;-122.261296
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111025T162600Z
|
||||
SUMMARY:UA5304 SBA to SFO
|
||||
LOCATION:Santa Barbara (SBA)
|
||||
UID:item-ae300a6934c3820974dba2c9c5b8fae843c67693@tripit.com
|
||||
DTSTART:20111025T150900Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Flight] 10/25/2011 United Airlines(UA) #5304 dep S
|
||||
BA 8:09am PDT arr SFO 9:26am PDT\; John Doe Ticket #037871720263
|
||||
8\; seat(s) 11B\; conf #A44XS5\, PRX98G\, FYYJZ4 \nBooked on http://www.am
|
||||
ericanexpress-travel.com/\; Reference #: 7128 8086 8504\; http://www.ameri
|
||||
canexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716\; Total
|
||||
Cost: $699.99 \n \n \n\nTripIt - organize your travel at http://www.tripit
|
||||
.com
|
||||
GEO:37.618889;-122.375
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Pick-up Rental Car: Hertz
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-2a9fd5a57a4cdda4677fc6ce23738e1954fdbe2a@tripit.com
|
||||
DTSTART:20111025T163000Z
|
||||
DTEND:20111025T173000Z
|
||||
LOCATION:780 McDonnell Road\, San Francisco\, CA\, 94128
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Car Rental] Hertz\; San Francisco International Ai
|
||||
rport\; primary driver John Doe\; conf #F2633064194 \n780 McDonn
|
||||
ell Road\, San Francisco\, CA\, 94128 \npickup 10/25/2011 9:30am\; dropoff
|
||||
10/27/2011 7:00pm \nToyota Corolla or similar\; 84.57 USD \nBooked on htt
|
||||
p://www.hertz.com/\; Reference #: F2633064194\; http://www.hertz.com/\; 80
|
||||
0-654-3131\; Booking Rate: 84.57 USD\; Total Cost: 333.76 USD \n \n \n\nTr
|
||||
ipIt - organize your travel at http://www.tripit.com
|
||||
GEO:37.6297569;-122.4000351
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-98dfcb0bcfdcffcce9c58a84947212ed67cadda6@tripit.com
|
||||
DTSTART:20111025T163600Z
|
||||
DTEND:20111025T173600Z
|
||||
SUMMARY:Directions from SFO to Sofitel San Francisco Bay
|
||||
LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Directions] 10/25/2011 9:36am - Directions from SF
|
||||
O to Sofitel San Francisco Bay \nfrom: SFO \nto: 223 Twin Dolphin Drive\,
|
||||
Redwood City\, CA\, 94065 \nView directions here: http://maps.google.com/m
|
||||
aps?output=mobile&saddr=SFO&daddr=223+Twin+Dolphin+Drive%2C+Redwood+City%2
|
||||
C+CA%2C+94065 \n \n \n\nTripIt - organize your travel at http://www.tripit
|
||||
.com
|
||||
GEO:37.5232475;-122.261296
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-in: Sofitel San Francisco Bay
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-8de3937b336c333faf2d55ad0a41c5ca6cc02393@tripit.com
|
||||
DTSTART:20111025T220000Z
|
||||
DTEND:20111025T230000Z
|
||||
LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Lodging] Sofitel San Francisco Bay\; primary guest
|
||||
John Doe\; conf #F80-0GMW \n223 Twin Dolphin Drive\, Redwood Ci
|
||||
ty\, CA\, 94065\; tel (+1)650/598-9000 \narrive 10/25/2011\; depart 10/27/
|
||||
2011\; rooms: 1 \nBooked on http://www.sofitel.com/\; http://www.sofitel.c
|
||||
om/\; Total Cost: 564.00 USD \n \n \n\nTripIt - organize your travel at ht
|
||||
tp://www.tripit.com
|
||||
GEO:37.5232475;-122.261296
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-out: Sofitel San Francisco Bay
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-f3ade58646964bde101616a6d26ea7784a1a81e8@tripit.com
|
||||
DTSTART:20111027T190000Z
|
||||
DTEND:20111027T200000Z
|
||||
LOCATION:223 Twin Dolphin Drive\, Redwood City\, CA\, 94065
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Lodging] Sofitel San Francisco Bay\; primary guest
|
||||
John Doe\; conf #F80-0GMW \n223 Twin Dolphin Drive\, Redwood Ci
|
||||
ty\, CA\, 94065\; tel (+1)650/598-9000 \narrive 10/25/2011\; depart 10/27/
|
||||
2011\; rooms: 1 \nBooked on http://www.sofitel.com/\; http://www.sofitel.c
|
||||
om/\; Total Cost: 564.00 USD \n \n \n\nTripIt - organize your travel at ht
|
||||
tp://www.tripit.com
|
||||
GEO:37.5232475;-122.261296
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Drop-off Rental Car: Hertz
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-50620273fea0614d37775649034d5e1de92ae361@tripit.com
|
||||
DTSTART:20111028T020000Z
|
||||
DTEND:20111028T030000Z
|
||||
LOCATION:780 McDonnell Road\, San Francisco\, CA\, 94128
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Car Rental] Hertz\; San Francisco International Ai
|
||||
rport\; primary driver John Doe\; conf #F2633064194 \n780 McDonn
|
||||
ell Road\, San Francisco\, CA\, 94128 \npickup 10/25/2011 9:30am\; dropoff
|
||||
10/27/2011 7:00pm \nToyota Corolla or similar\; 84.57 USD \nBooked on htt
|
||||
p://www.hertz.com/\; Reference #: F2633064194\; http://www.hertz.com/\; 80
|
||||
0-654-3131\; Booking Rate: 84.57 USD\; Total Cost: 333.76 USD \n \n \n\nTr
|
||||
ipIt - organize your travel at http://www.tripit.com
|
||||
GEO:37.6297569;-122.4000351
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111028T051900Z
|
||||
SUMMARY:CO6256 SFO to PHX
|
||||
LOCATION:San Francisco (SFO)
|
||||
UID:item-71d327f30d8beeaf7bf50c8fa63ce16005b9b0df@tripit.com
|
||||
DTSTART:20111028T031900Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24259445\n \n[Flight] 10/27/2011 Continental Airlines(CO) #6256
|
||||
dep SFO 8:19pm PDT arr PHX 10:19pm MST\; John Doe Ticket #037871
|
||||
7202638\; seat(s) 17D\; conf #A44XS5\, PRX98G\, FYYJZ4(Operated by United
|
||||
Airlines flight 6256) \nBooked on http://www.americanexpress-travel.com/\;
|
||||
Reference #: 7128 8086 8504\; http://www.americanexpress-travel.com/\; US
|
||||
:1-800-297-2977\, Outside:210-582-2716\; Total Cost: $699.99 \n \n \n\nTri
|
||||
pIt - organize your travel at http://www.tripit.com
|
||||
GEO:33.436111;-112.009444
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
UID:2d4b446e63a94ade7dab0f0e9546b2d1965f011c@tripit.com
|
||||
DTSTART;VALUE=DATE:20111108
|
||||
DTEND;VALUE=DATE:20111111
|
||||
SUMMARY:Redwood City\, CA\, November 2011
|
||||
LOCATION:Redwood City\, CA
|
||||
GEO:37.485215;-122.236355
|
||||
TRANSP:TRANSPARENT
|
||||
DESCRIPTION:John Doe is in Redwood City\, CA from Nov 8 to Nov 1
|
||||
0\, 2011\nView and/or edit details in TripIt : http://www.tripit.com/trip/
|
||||
show/id/24913749\nTripIt - organize your travel at http://www.tripit.com\n
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111108T175700Z
|
||||
SUMMARY:US403 PHX to SFO
|
||||
LOCATION:Phoenix (PHX)
|
||||
UID:item-7de7d829b2f95991de6d01c3d68f24b84770168c@tripit.com
|
||||
DTSTART:20111108T154500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24913749\n \n[Flight] 11/8/2011 US Airways(US) #403 dep PHX 8:45
|
||||
am MST arr SFO 9:57am PST\; John Doe\; seat(s) 21C\; conf #FJDX0
|
||||
J\, I2W8HW \nBooked on http://www.americanexpress-travel.com/\; Reference
|
||||
#: 4129 9623 4732\; http://www.americanexpress-travel.com/\; US:1-800-297-
|
||||
2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at htt
|
||||
p://www.tripit.com
|
||||
GEO:37.618889;-122.375
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Pick-up Rental Car: Dollar Rent A Car
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-1ac6982fefdd79bc5ea849785f415a6291c450b1@tripit.com
|
||||
DTSTART:20111108T182700Z
|
||||
DTEND:20111108T192700Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24913749\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte
|
||||
rnational Airport\; primary driver John Doe\; conf #Q0058133 \np
|
||||
ickup 11/8/2011 10:27am\; dropoff 11/10/2011 6:25pm \nEconomy \nBooked on
|
||||
http://www.americanexpress-travel.com/\; Reference #: 4129 9623 4732\; htt
|
||||
p://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-
|
||||
2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-in: Sofitel San Francisco Bay
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-126e584ffbefbec32a15ca503f0bdf8d3f9cc2f4@tripit.com
|
||||
DTSTART:20111108T195700Z
|
||||
DTEND:20111108T205700Z
|
||||
LOCATION:223 TWIN DOLPHIN DR\, Redwood City\, CA\, 94065-1514
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24913749\n \n[Lodging] Sofitel San Francisco Bay\; primary guest
|
||||
John Doe\; conf #Q0058133 \n223 TWIN DOLPHIN DR\, Redwood City\
|
||||
, CA\, 94065-1514\; tel 1.650.598.9000 \narrive 11/8/2011\; depart 11/10/2
|
||||
011\; rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Refere
|
||||
nce #: 4129 9623 4732\; http://www.americanexpress-travel.com/\; US:1-800-
|
||||
297-2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at
|
||||
http://www.tripit.com
|
||||
GEO:37.5232475;-122.261296
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-out: Sofitel San Francisco Bay
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-ff48c502022356ccaa862ebb61761a0de08a1ce9@tripit.com
|
||||
DTSTART:20111111T015500Z
|
||||
DTEND:20111111T025500Z
|
||||
LOCATION:223 TWIN DOLPHIN DR\, Redwood City\, CA\, 94065-1514
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24913749\n \n[Lodging] Sofitel San Francisco Bay\; primary guest
|
||||
John Doe\; conf #Q0058133 \n223 TWIN DOLPHIN DR\, Redwood City\
|
||||
, CA\, 94065-1514\; tel 1.650.598.9000 \narrive 11/8/2011\; depart 11/10/2
|
||||
011\; rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Refere
|
||||
nce #: 4129 9623 4732\; http://www.americanexpress-travel.com/\; US:1-800-
|
||||
297-2977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at
|
||||
http://www.tripit.com
|
||||
GEO:37.5232475;-122.261296
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Drop-off Rental Car: Dollar Rent A Car
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-c0273c03ddbb68a9b05d5d43a489bc318136ca42@tripit.com
|
||||
DTSTART:20111111T022500Z
|
||||
DTEND:20111111T032500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24913749\n \n[Car Rental] Dollar Rent A Car\; San Francisco Inte
|
||||
rnational Airport\; primary driver John Doe\; conf #Q0058133 \np
|
||||
ickup 11/8/2011 10:27am\; dropoff 11/10/2011 6:25pm \nEconomy \nBooked on
|
||||
http://www.americanexpress-travel.com/\; Reference #: 4129 9623 4732\; htt
|
||||
p://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-
|
||||
2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111111T055400Z
|
||||
SUMMARY:CO496 SFO to PHX
|
||||
LOCATION:San Francisco (SFO)
|
||||
UID:item-3473cf9275326ac393b37859df3b04306b4849aa@tripit.com
|
||||
DTSTART:20111111T035500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/24913749\n \n[Flight] 11/10/2011 Continental Airlines(CO) #496 d
|
||||
ep SFO 7:55pm PST arr PHX 10:54pm MST\; John Doe\; seat(s) 26B\;
|
||||
conf #FJDX0J\, I2W8HW(Operated by United Airlines flight 496) \nBooked on
|
||||
http://www.americanexpress-travel.com/\; Reference #: 4129 9623 4732\; ht
|
||||
tp://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582
|
||||
-2716 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
GEO:33.436111;-112.009444
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
UID:4ee5ded058432990e3d8808f48ca851e04923b6d@tripit.com
|
||||
DTSTART;VALUE=DATE:20111129
|
||||
DTEND;VALUE=DATE:20111202
|
||||
SUMMARY:Milpitas\, CA\, November 2011
|
||||
LOCATION:Milpitas\, CA
|
||||
GEO:37.428272;-121.906624
|
||||
TRANSP:TRANSPARENT
|
||||
DESCRIPTION:John Doe is in Milpitas\, CA from Nov 29 to Dec 1\,
|
||||
2011\nView and/or edit details in TripIt : http://www.tripit.com/trip/show
|
||||
/id/25671681\nTripIt - organize your travel at http://www.tripit.com\n
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111129T172400Z
|
||||
SUMMARY:US282 PHX to SJC
|
||||
LOCATION:Phoenix (PHX)
|
||||
UID:item-644d5973b50d521d50e475ccf5321605d54bd0d5@tripit.com
|
||||
DTSTART:20111129T152500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/25671681\n \n[Flight] 11/29/2011 US Airways(US) #282 dep PHX 8:2
|
||||
5am MST arr SJC 9:24am PST\; John Doe\; seat(s) 17C\; conf #DQKD
|
||||
GY \nBooked on http://www.americanexpress-travel.com/\; Reference #: 4131
|
||||
3301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2977\, O
|
||||
utside:210-582-2716 \n \n \n\nTripIt - organize your travel at http://www.
|
||||
tripit.com
|
||||
GEO:37.361111;-121.925556
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Pick-up Rental Car: Alamo
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-10368bbdbc9b6f26f83098500633cc4eb604c751@tripit.com
|
||||
DTSTART:20111129T175400Z
|
||||
DTEND:20111129T185400Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/25671681\n \n[Car Rental] Alamo\; San Jose International Airport
|
||||
\; primary driver John Doe\; conf #372828149COUNT \npickup 11/29
|
||||
/2011 9:54am\; dropoff 12/1/2011 5:45pm \nIntermediate \nBooked on http://
|
||||
www.americanexpress-travel.com/\; Reference #: 4131 3301 9911\; http://www
|
||||
.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n
|
||||
\n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-in: The Beverly Heritage Hotel
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-98d8638d3f1c011d03cb8f58b3a14a0f1203339b@tripit.com
|
||||
DTSTART:20111129T192400Z
|
||||
DTEND:20111129T202400Z
|
||||
LOCATION:1820 Barber Lane\, Milpitas\, CA\, 95035
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/25671681\n \n[Lodging] The Beverly Heritage Hotel\; primary gues
|
||||
t John Doe\; conf #372828149COUNT \n1820 Barber Lane\, Milpitas\
|
||||
, CA\, 95035\; tel 1.408.943.9080 \narrive 11/29/2011\; depart 12/1/2011\;
|
||||
rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Reference #
|
||||
: 4131 3301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2
|
||||
977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at http
|
||||
://www.tripit.com
|
||||
GEO:37.4010467;-121.9116284
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111201T194400Z
|
||||
SUMMARY:US273 SJC to PHX
|
||||
LOCATION:San Jose (SJC)
|
||||
UID:item-7b9ee9bb4edfe69743e32b33f9be55753956a883@tripit.com
|
||||
DTSTART:20111201T175900Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/25671681\n \n[Flight] 12/1/2011 US Airways(US) #273 dep SJC 9:59
|
||||
am PST arr PHX 12:44pm MST\; John Doe Ticket #0378727451156\; co
|
||||
nf #EMF71T \nBooked on http://www.americanexpress-travel.com/\; Reference
|
||||
#: 5133 5264 1627\; http://www.americanexpress-travel.com/\; US:1-800-297-
|
||||
2977\, Outside:210-582-2716\; Total Cost: $316.69 \n \n \n\nTripIt - organ
|
||||
ize your travel at http://www.tripit.com
|
||||
GEO:33.436111;-112.009444
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-out: The Beverly Heritage Hotel
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-f79f203072002b8f06598dcb2be0e36af17b625b@tripit.com
|
||||
DTSTART:20111202T011500Z
|
||||
DTEND:20111202T021500Z
|
||||
LOCATION:1820 Barber Lane\, Milpitas\, CA\, 95035
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/25671681\n \n[Lodging] The Beverly Heritage Hotel\; primary gues
|
||||
t John Doe\; conf #372828149COUNT \n1820 Barber Lane\, Milpitas\
|
||||
, CA\, 95035\; tel 1.408.943.9080 \narrive 11/29/2011\; depart 12/1/2011\;
|
||||
rooms: 1 \nBooked on http://www.americanexpress-travel.com/\; Reference #
|
||||
: 4131 3301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2
|
||||
977\, Outside:210-582-2716 \n \n \n\nTripIt - organize your travel at http
|
||||
://www.tripit.com
|
||||
GEO:37.4010467;-121.9116284
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Drop-off Rental Car: Alamo
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-69f526ad49fa8ca0a74486f4fc77cc3f9d23a72f@tripit.com
|
||||
DTSTART:20111202T014500Z
|
||||
DTEND:20111202T024500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/25671681\n \n[Car Rental] Alamo\; San Jose International Airport
|
||||
\; primary driver John Doe\; conf #372828149COUNT \npickup 11/29
|
||||
/2011 9:54am\; dropoff 12/1/2011 5:45pm \nIntermediate \nBooked on http://
|
||||
www.americanexpress-travel.com/\; Reference #: 4131 3301 9911\; http://www
|
||||
.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:210-582-2716 \n
|
||||
\n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111202T045900Z
|
||||
SUMMARY:US288 SJC to PHX
|
||||
LOCATION:San Jose (SJC)
|
||||
UID:item-dab68a87c8dd49064ab0ba1dec5ba75ba46ff1d3@tripit.com
|
||||
DTSTART:20111202T031500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/25671681\n \n[Flight] 12/1/2011 US Airways(US) #288 dep SJC 7:15
|
||||
pm PST arr PHX 9:59pm MST\; John Doe\; seat(s) 13C\; conf #DQKDG
|
||||
Y \nBooked on http://www.americanexpress-travel.com/\; Reference #: 4131 3
|
||||
301 9911\; http://www.americanexpress-travel.com/\; US:1-800-297-2977\, Ou
|
||||
tside:210-582-2716 \n \n \n\nTripIt - organize your travel at http://www.t
|
||||
ripit.com
|
||||
GEO:33.436111;-112.009444
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
UID:67d48ddde166a2e9bbac2cf7d93fe493b0860008@tripit.com
|
||||
DTSTART;VALUE=DATE:20111213
|
||||
DTEND;VALUE=DATE:20111216
|
||||
SUMMARY:San Jose\, CA\, December 2011
|
||||
LOCATION:San Jose\, CA
|
||||
GEO:37.339386;-121.894955
|
||||
TRANSP:TRANSPARENT
|
||||
DESCRIPTION:John Doe is in San Jose\, CA from Dec 13 to Dec 15\,
|
||||
2011\nView and/or edit details in TripIt : http://www.tripit.com/trip/sho
|
||||
w/id/27037117\nTripIt - organize your travel at http://www.tripit.com\n
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111213T172400Z
|
||||
SUMMARY:US282 PHX to SJC
|
||||
LOCATION:Phoenix (PHX)
|
||||
UID:item-2b1b9021be548a87dd335f190b60ab78c33b619d@tripit.com
|
||||
DTSTART:20111213T152500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27037117\n \n[Flight] 12/13/2011 US Airways(US) #282 dep PHX 8:2
|
||||
5am MST arr SJC 9:24am PST\; John Doe Ticket #0378728465928\; se
|
||||
at(s) 15C\; conf #GGNV29 \nBooked on http://www.americanexpress-travel.com
|
||||
/\; Reference #: 3134 0525 5102\; http://www.americanexpress-travel.com/\;
|
||||
US:1-800-297-2977\, Outside:210-582-2716\; Total Cost: $406.39 \n \n \n\n
|
||||
TripIt - organize your travel at http://www.tripit.com
|
||||
GEO:37.361111;-121.925556
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Pick-up Rental Car: Advantage
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-619d345bb08aaef68e8767b672277243697f5bff@tripit.com
|
||||
DTSTART:20111213T180000Z
|
||||
DTEND:20111213T190000Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27037117\n \n[Car Rental] Advantage\; San Jose International Air
|
||||
port\; primary driver John Doe\; conf #F31539020E7 \npickup 12/1
|
||||
3/2011 10:00am\; dropoff 12/15/2011 7:00pm \nStandard Convertible \nRefere
|
||||
nce #: 3134 0526 3890 \n \n \n\nTripIt - organize your travel at http://ww
|
||||
w.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-in: Crestview Hotel:
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-fbe6c08e7523c82fac69b40ad1d0899f3d8d5982@tripit.com
|
||||
DTSTART:20111213T192400Z
|
||||
DTEND:20111213T202400Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27037117\n \n[Lodging] Crestview Hotel:\; conf #CR31342159 \ntel
|
||||
650-966-8848 \narrive 12/13/2011\; depart 12/15/2011 \nBooking Rate: 153.
|
||||
30 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-out: Crestview Hotel:
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-7ed8b84628e650a6b37161c7825bac9e72add49f@tripit.com
|
||||
DTSTART:20111216T011500Z
|
||||
DTEND:20111216T021500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27037117\n \n[Lodging] Crestview Hotel:\; conf #CR31342159 \ntel
|
||||
650-966-8848 \narrive 12/13/2011\; depart 12/15/2011 \nBooking Rate: 153.
|
||||
30 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Drop-off Rental Car: Advantage
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-623b54ebe07ffd48845f1a120a86940ce79c698b@tripit.com
|
||||
DTSTART:20111216T030000Z
|
||||
DTEND:20111216T040000Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27037117\n \n[Car Rental] Advantage\; San Jose International Air
|
||||
port\; primary driver John Doe\; conf #F31539020E7 \npickup 12/1
|
||||
3/2011 10:00am\; dropoff 12/15/2011 7:00pm \nStandard Convertible \nRefere
|
||||
nce #: 3134 0526 3890 \n \n \n\nTripIt - organize your travel at http://ww
|
||||
w.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20111216T045900Z
|
||||
SUMMARY:US288 SJC to PHX
|
||||
LOCATION:San Jose (SJC)
|
||||
UID:item-52481e672972d2e88d5eaa5cf49bb801562c6014@tripit.com
|
||||
DTSTART:20111216T031500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27037117\n \n[Flight] 12/15/2011 US Airways(US) #288 dep SJC 7:1
|
||||
5pm PST arr PHX 9:59pm MST\; John Doe Ticket #0378728465928\; se
|
||||
at(s) 7B\; conf #GGNV29 \nBooked on http://www.americanexpress-travel.com/
|
||||
\; Reference #: 3134 0525 5102\; http://www.americanexpress-travel.com/\;
|
||||
US:1-800-297-2977\, Outside:210-582-2716\; Total Cost: $406.39 \n \n \n\nT
|
||||
ripIt - organize your travel at http://www.tripit.com
|
||||
GEO:33.436111;-112.009444
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
UID:7299ff29daed7d5c3e2ed4acc74deec5b7942bd5@tripit.com
|
||||
DTSTART;VALUE=DATE:20120103
|
||||
DTEND;VALUE=DATE:20120106
|
||||
SUMMARY:San Francisco\, CA\, January 2012
|
||||
LOCATION:San Francisco\, CA
|
||||
GEO:37.774929;-122.419415
|
||||
TRANSP:TRANSPARENT
|
||||
DESCRIPTION:John Doe is in San Francisco\, CA from Jan 3 to Jan
|
||||
5\, 2012\nView and/or edit details in TripIt : http://www.tripit.com/trip/
|
||||
show/id/27863159\nTripIt - organize your travel at http://www.tripit.com\n
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20120103T175700Z
|
||||
SUMMARY:US403 PHX to SFO
|
||||
LOCATION:Phoenix (PHX)
|
||||
UID:item-f099e76114bf43ef3b122432579d8b40995412a7@tripit.com
|
||||
DTSTART:20120103T154500Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27863159\n \n[Flight] 1/3/2012 US Airways(US) #403 dep PHX 8:45a
|
||||
m MST arr SFO 9:57am PST\; John Doe Ticket #0378731791515\; conf
|
||||
#FH9B72\, L4F9M5 \nBooked on http://www.americanexpress-travel.com/\; Ref
|
||||
erence #: 6135 7391 6119\; http://www.americanexpress-travel.com/\; US:1-8
|
||||
00-297-2977\, Outside:210-582-2716\; Total Cost: $668.39 \n \n \n\nTripIt
|
||||
- organize your travel at http://www.tripit.com
|
||||
GEO:37.618889;-122.375
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Pick-up Rental Car: Alamo
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-fae4b4b07b66fc87df125238e0aaf645106cf4f3@tripit.com
|
||||
DTSTART:20120103T180000Z
|
||||
DTEND:20120103T190000Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27863159\n \n[Car Rental] Alamo\; San Francisco International Ai
|
||||
rport\; primary driver John Doe\; conf #373525981COUNT \npickup
|
||||
1/3/2012 10:00am\; dropoff 1/5/2012 6:00pm \nCompact \nReference #: 6135 7
|
||||
391 6898 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-in: Grand Hotel Sunnyvale
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-d89a856eb9da9dfdcb4da46f42e49af3a838fcbb@tripit.com
|
||||
DTSTART:20120103T195700Z
|
||||
DTEND:20120103T205700Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27863159\n \n[Lodging] Grand Hotel Sunnyvale\; conf #22084SY0361
|
||||
18 \ntel 1-408-7208500 \narrive 1/3/2012\; depart 1/5/2012 \nBooking Rate:
|
||||
USD 169.00 \nPolicies: Guarantee to valid form of payment is required at
|
||||
time of booking\; Cancel 1 day prior to arrival date to avoid penalty of 1
|
||||
Nights Room Charge. Change fee may apply for early departures and changes
|
||||
made to confirmed reservations.\; \n \n \n\nTripIt - organize your travel
|
||||
at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Check-out: Grand Hotel Sunnyvale
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-6edc82f6411fd0b66f2f7f6baafa41623a8623a9@tripit.com
|
||||
DTSTART:20120106T010900Z
|
||||
DTEND:20120106T020900Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27863159\n \n[Lodging] Grand Hotel Sunnyvale\; conf #22084SY0361
|
||||
18 \ntel 1-408-7208500 \narrive 1/3/2012\; depart 1/5/2012 \nBooking Rate:
|
||||
USD 169.00 \nPolicies: Guarantee to valid form of payment is required at
|
||||
time of booking\; Cancel 1 day prior to arrival date to avoid penalty of 1
|
||||
Nights Room Charge. Change fee may apply for early departures and changes
|
||||
made to confirmed reservations.\; \n \n \n\nTripIt - organize your travel
|
||||
at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
SUMMARY:Drop-off Rental Car: Alamo
|
||||
TRANSP:TRANSPARENT
|
||||
UID:item-58a31b96066ffd09b800af49de59a84f7b7a3a06@tripit.com
|
||||
DTSTART:20120106T020000Z
|
||||
DTEND:20120106T030000Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27863159\n \n[Car Rental] Alamo\; San Francisco International Ai
|
||||
rport\; primary driver John Doe\; conf #373525981COUNT \npickup
|
||||
1/3/2012 10:00am\; dropoff 1/5/2012 6:00pm \nCompact \nReference #: 6135 7
|
||||
391 6898 \n \n \n\nTripIt - organize your travel at http://www.tripit.com
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20120101T215311Z
|
||||
DTEND:20120106T050500Z
|
||||
SUMMARY:CO496 SFO to PHX
|
||||
LOCATION:San Francisco (SFO)
|
||||
UID:item-7884351ce42d503b90ccc48c33c7c30bd4f44767@tripit.com
|
||||
DTSTART:20120106T030900Z
|
||||
DESCRIPTION:View and/or edit details in TripIt : http://www.tripit.com/tri
|
||||
p/show/id/27863159\n \n[Flight] 1/5/2012 Continental Airlines(CO) #496 dep
|
||||
SFO 7:09pm PST arr PHX 10:05pm MST\; John Doe Ticket #037873179
|
||||
1515\; conf #FH9B72\, L4F9M5(Operated by United Airlines flight 496) \nBoo
|
||||
ked on http://www.americanexpress-travel.com/\; Reference #: 6135 7391 611
|
||||
9\; http://www.americanexpress-travel.com/\; US:1-800-297-2977\, Outside:2
|
||||
10-582-2716\; Total Cost: $668.39 \n \n \n\nTripIt - organize your travel
|
||||
at http://www.tripit.com
|
||||
GEO:33.436111;-112.009444
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@ -1,41 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:-//Meetup//RemoteApi//EN
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-ORIGINAL-URL:http://www.meetup.com/events/ical/8333638/dfdba2e469216075
|
||||
3404f737feace78d526ff0ce/going
|
||||
X-WR-CALNAME:My Meetups
|
||||
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/Phoenix
|
||||
TZURL:http://tzurl.org/zoneinfo-outlook/America/Phoenix
|
||||
X-LIC-LOCATION:America/Phoenix
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0700
|
||||
TZOFFSETTO:-0700
|
||||
TZNAME:MST
|
||||
DTSTART:19700101T000000
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTAMP:20111106T155927Z
|
||||
DTSTART;TZID=America/Phoenix:20111109T190000
|
||||
DTEND;TZID=America/Phoenix:20111109T210000
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:Phoenix Drupal User Group Monthly Meetup
|
||||
DESCRIPTION:Phoenix Drupal User Group\nWednesday\, November 9 at 7:00 PM\
|
||||
n\nCustomizing node display with template pages in Drupal 6\n\n Jon Shee
|
||||
han and Matthew Berry of the Office of Knowledge Enterprise Development
|
||||
(OKED) Knowledge...\n\nDetails: http://www.meetup.com/Phoenix-Drupal-Use
|
||||
r-Group/events/33627272/
|
||||
CLASS:PUBLIC
|
||||
CREATED:20100630T083023Z
|
||||
GEO:33.56;-111.90
|
||||
LOCATION:Open Source Project Tempe (1415 E University Dr. #103A\, Tempe\,
|
||||
AZ 85281)
|
||||
URL:http://www.meetup.com/Phoenix-Drupal-User-Group/events/33627272/
|
||||
LAST-MODIFIED:20111102T213309Z
|
||||
UID:event_nsmxnyppbfc@meetup.com
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
1170
modules/default/calendar/vendor/ical.js/test/test6.ics
vendored
1170
modules/default/calendar/vendor/ical.js/test/test6.ics
vendored
File diff suppressed because it is too large
Load Diff
@ -1,16 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:ownCloud Calendar 0.6.3
|
||||
X-WR-CALNAME:Fête Nationale - Férié
|
||||
BEGIN:VEVENT
|
||||
CREATED:20090502T140513Z
|
||||
DTSTAMP:20111106T124709Z
|
||||
UID:FA9831E7-C238-4FEC-95E5-CD46BD466421
|
||||
SUMMARY:Fête Nationale - Férié
|
||||
RRULE:FREQ=YEARLY
|
||||
DTSTART;VALUE=DATE:20120714
|
||||
DTEND;VALUE=DATE:20120715
|
||||
TRANSP:OPAQUE
|
||||
SEQUENCE:5
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
@ -1,23 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:ownCloud Calendar 0.6.3
|
||||
X-WR-CALNAME:Default calendar
|
||||
BEGIN:VTODO
|
||||
CREATED;VALUE=DATE-TIME:20130714T092804Z
|
||||
UID:0aa462f13c
|
||||
LAST-MODIFIED;VALUE=DATE-TIME:20130714T092804Z
|
||||
DTSTAMP;VALUE=DATE-TIME:20130714T092804Z
|
||||
CATEGORIES:Projets
|
||||
SUMMARY:Migrer le blog
|
||||
PERCENT-COMPLETE:100
|
||||
COMPLETED;VALUE=DATE-TIME;TZID=Europe/Monaco:20130716T105745
|
||||
END:VTODO
|
||||
BEGIN:VTODO
|
||||
CREATED;VALUE=DATE-TIME:20130714T092912Z
|
||||
UID:5e05bbcf34
|
||||
LAST-MODIFIED;VALUE=DATE-TIME:20130714T092912Z
|
||||
DTSTAMP;VALUE=DATE-TIME:20130714T092912Z
|
||||
SUMMARY:Créer test unitaire erreur ical
|
||||
CATEGORIES:Projets
|
||||
END:VTODO
|
||||
END:VCALENDAR
|
@ -1,21 +0,0 @@
|
||||
BEGIN:VCALENDAR
|
||||
BEGIN:VEVENT
|
||||
UID:eb9e1bd2-ceba-499f-be77-f02773954c72
|
||||
SUMMARY:Event with an alarm
|
||||
DESCRIPTION:This is an event with an alarm.
|
||||
ORGANIZER="mailto:stomlinson@mozilla.com"
|
||||
DTSTART;TZID="America/Los_Angeles":20130418T110000
|
||||
DTEND;TZID="America/Los_Angeles":20130418T120000
|
||||
STATUS:CONFIRMED
|
||||
CLASS:PUBLIC
|
||||
TRANSP:OPAQUE
|
||||
LAST-MODIFIED:20130418T175632Z
|
||||
DTSTAMP:20130418T175632Z
|
||||
SEQUENCE:3
|
||||
BEGIN:VALARM
|
||||
ACTION:DISPLAY
|
||||
TRIGGER;RELATED=START:-PT5M
|
||||
DESCRIPTION:Reminder
|
||||
END:VALARM
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
1151
package-lock.json
generated
1151
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -15,6 +15,7 @@
|
||||
"test:prettier": "prettier --check **/*.{js,css,json,md,yml}",
|
||||
"test:js": "eslint *.js js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --quiet",
|
||||
"test:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json",
|
||||
"test:calendar": "node ./modules/default/calendar/debug.js",
|
||||
"config:check": "node js/check_config.js",
|
||||
"lint:prettier": "prettier --write **/*.{js,css,json,md,yml}",
|
||||
"lint:js": "eslint *.js js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --fix",
|
||||
@ -46,7 +47,7 @@
|
||||
"current-week-number": "^1.0.7",
|
||||
"danger": "^3.1.3",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"http-auth": "^3.2.3",
|
||||
"husky": "^4.2.5",
|
||||
"jsdom": "^11.6.2",
|
||||
@ -56,8 +57,8 @@
|
||||
"prettier": "^2.0.5",
|
||||
"pretty-quick": "^2.0.1",
|
||||
"spectron": "^8.0.0",
|
||||
"stylelint": "^13.3.3",
|
||||
"stylelint-config-prettier": "^8.0.1",
|
||||
"stylelint": "^13.6.1",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint-prettier": "^1.1.2"
|
||||
},
|
||||
@ -67,16 +68,17 @@
|
||||
"dependencies": {
|
||||
"colors": "^1.1.2",
|
||||
"console-stamp": "^0.2.9",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint": "^7.3.0",
|
||||
"express": "^4.16.2",
|
||||
"express-ipfilter": "^1.0.1",
|
||||
"feedme": "latest",
|
||||
"helmet": "^3.21.2",
|
||||
"ical": "^0.8.0",
|
||||
"iconv-lite": "latest",
|
||||
"lodash": "^4.17.15",
|
||||
"module-alias": "^2.2.2",
|
||||
"moment": "latest",
|
||||
"request": "^2.88.0",
|
||||
"request": "^2.88.2",
|
||||
"rrule": "^2.6.2",
|
||||
"rrule-alt": "^2.2.8",
|
||||
"simple-git": "^1.85.0",
|
||||
|
Loading…
x
Reference in New Issue
Block a user