mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 19:53:36 +00:00
fix full date start time and duration, east of UTC, make getCorrection more understandable with variable name changes
This commit is contained in:
parent
568f952573
commit
9e5a9b5ced
@ -85,7 +85,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
};
|
};
|
||||||
|
|
||||||
const eventDate = function (event, time) {
|
const eventDate = function (event, time) {
|
||||||
return event[time].length === 8 ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
|
return isFullDayEvent(event) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.entries(data).forEach(([key, event]) => {
|
Object.entries(data).forEach(([key, event]) => {
|
||||||
@ -110,19 +110,22 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
if (event.type === "VEVENT") {
|
if (event.type === "VEVENT") {
|
||||||
let startDate = eventDate(event, "start");
|
let startDate = eventDate(event, "start");
|
||||||
let endDate;
|
let endDate;
|
||||||
// console.log("\nevent="+JSON.stringify(event))
|
// Log.debug("\nevent="+JSON.stringify(event))
|
||||||
if (typeof event.end !== "undefined") {
|
if (typeof event.end !== "undefined") {
|
||||||
endDate = eventDate(event, "end");
|
endDate = eventDate(event, "end");
|
||||||
} else if (typeof event.duration !== "undefined") {
|
} else if (typeof event.duration !== "undefined") {
|
||||||
endDate = startDate.clone().add(moment.duration(event.duration));
|
endDate = startDate.clone().add(moment.duration(event.duration));
|
||||||
} else {
|
} else {
|
||||||
if (!isFacebookBirthday) {
|
if (!isFacebookBirthday) {
|
||||||
endDate = startDate;
|
// make copy of start date, separate storage area
|
||||||
|
endDate = moment(startDate.format("x"), "x");
|
||||||
} else {
|
} else {
|
||||||
endDate = moment(startDate).add(1, "days");
|
endDate = moment(startDate).add(1, "days");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.debug(" start=" + startDate.toDate() + " end=" + endDate.toDate());
|
||||||
|
|
||||||
// calculate the duration of the event for use with recurring events.
|
// calculate the duration of the event for use with recurring events.
|
||||||
let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x"));
|
let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x"));
|
||||||
|
|
||||||
@ -212,9 +215,9 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate();
|
pastLocal = pastMoment.subtract(past.getTimezoneOffset(), "minutes").toDate();
|
||||||
futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate();
|
futureLocal = futureMoment.subtract(future.getTimezoneOffset(), "minutes").toDate();
|
||||||
}
|
}
|
||||||
|
Log.debug(" between=" + pastLocal + " to " + futureLocal);
|
||||||
const dates = rule.between(pastLocal, futureLocal, true, limitFunction);
|
const dates = rule.between(pastLocal, futureLocal, true, limitFunction);
|
||||||
// console.log("title="+event.summary.val+" dates="+JSON.stringify(dates))
|
Log.debug("title=" + event.summary + " dates=" + JSON.stringify(dates));
|
||||||
// The "dates" array contains the set of dates within our desired date range range that are valid
|
// 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,
|
// had its date changed from outside the range to inside the range. For the time being,
|
||||||
@ -231,10 +234,9 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through the set of date entries to see which recurrences should be added to our event list.
|
// Loop through the set of date entries to see which recurrences should be added to our event list.
|
||||||
for (let d in dates) {
|
for (let d in dates) {
|
||||||
const date = dates[d];
|
let date = dates[d];
|
||||||
// ical.js started returning recurrences and exdates as ISOStrings without time information.
|
// 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
|
// .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 )
|
// (see https://github.com/peterbraden/ical.js/pull/84 )
|
||||||
@ -242,54 +244,28 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
let curEvent = event;
|
let curEvent = event;
|
||||||
let showRecurrence = true;
|
let showRecurrence = true;
|
||||||
|
|
||||||
|
// for full day events, the time might be off from RRULE/Luxon problem
|
||||||
|
if (isFullDayEvent(event)) {
|
||||||
|
Log.debug("fullday");
|
||||||
|
// if the offset is negative, east of GMT where the problem is
|
||||||
|
if (date.getTimezoneOffset() < 0) {
|
||||||
|
// get the offset of today where we are processing
|
||||||
|
// this will be the correction we need to apply
|
||||||
|
let nowOffset = new Date().getTimezoneOffset();
|
||||||
|
Log.debug("now offset is " + nowOffset);
|
||||||
|
// reduce the time by the offset
|
||||||
|
Log.debug(" recurring date is " + date + " offset is " + date.getTimezoneOffset());
|
||||||
|
// apply the correction to the date/time to get it UTC relative
|
||||||
|
date = new Date(date.getTime() - Math.abs(nowOffset) * 60000);
|
||||||
|
// the duration was calculated way back at the top before we could correct the start time..
|
||||||
|
// fix it for this event entry
|
||||||
|
duration = 24 * 60 * 60 * 1000;
|
||||||
|
Log.debug("new recurring date is " + date);
|
||||||
|
}
|
||||||
|
}
|
||||||
startDate = moment(date);
|
startDate = moment(date);
|
||||||
// console.log("now timezone="+ moment.tz.guess());
|
|
||||||
// whether we need to adjust for RRULE returning the wrong date, with the right time (forward of URC timezones)
|
let adjustDays = getCorrection(event, date);
|
||||||
let adjustDays = 0;
|
|
||||||
// if a timezone was specified
|
|
||||||
if (!event.start.tz) {
|
|
||||||
event.start.tz = moment.tz.guess();
|
|
||||||
}
|
|
||||||
// console.log("tz="+event.start.tz)
|
|
||||||
if (event.start.tz) {
|
|
||||||
// if this is a windows timezone
|
|
||||||
if (event.start.tz.indexOf(" ") > 0) {
|
|
||||||
// use the lookup table to get theIANA name as moment and date don't know MS timezones
|
|
||||||
let tz = getIanaTZFromMS(event.start.tz);
|
|
||||||
// watch out for unregistered windows timezone names
|
|
||||||
// if we had a successfule lookup
|
|
||||||
if (tz) {
|
|
||||||
// change the timezone to the IANA name
|
|
||||||
event.start.tz = getIanaTZFromMS(event.start.tz);
|
|
||||||
// console.log("corrected timezone="+event.start.tz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get the start time in that timezone
|
|
||||||
let mms = moment.tz(moment(event.start), event.start.tz).utcOffset();
|
|
||||||
// console.log("ms offset="+mms)
|
|
||||||
// get the specified date in that timezone
|
|
||||||
let mm = moment.tz(moment(date), event.start.tz);
|
|
||||||
let mmo = mm.utcOffset();
|
|
||||||
// console.log("mm ofset="+ mmo+" hour="+mm.format("H")+" event date="+mm.toDate())
|
|
||||||
// if the offset is greater than 0, east of london
|
|
||||||
if (mmo > 0) {
|
|
||||||
let h = parseInt(mm.format("H"));
|
|
||||||
// check if the event time is less than the offset
|
|
||||||
if (h > 0 && h < mmo / 60) {
|
|
||||||
// if so, rrule created a wrong date (utc day, oops, with utc yesterday adjusted time)
|
|
||||||
// we need to fix that
|
|
||||||
adjustDays = 24;
|
|
||||||
// console.log("adjusting date")
|
|
||||||
}
|
|
||||||
if (mmo > mms) {
|
|
||||||
adjustDays += 1;
|
|
||||||
// console.log("adjust up 1 hour dst change")
|
|
||||||
} else if (mmo < mms) {
|
|
||||||
adjustDays -= 1;
|
|
||||||
//console.log("adjust down 1 hour dst change")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) {
|
||||||
@ -304,7 +280,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
showRecurrence = false;
|
showRecurrence = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("duration="+duration)
|
Log.debug("duration=" + duration);
|
||||||
|
|
||||||
endDate = moment(parseInt(startDate.format("x")) + duration, "x");
|
endDate = moment(parseInt(startDate.format("x")) + duration, "x");
|
||||||
if (startDate.format("x") === endDate.format("x")) {
|
if (startDate.format("x") === endDate.format("x")) {
|
||||||
@ -327,8 +303,8 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
addedEvents++;
|
addedEvents++;
|
||||||
newEvents.push({
|
newEvents.push({
|
||||||
title: recurrenceTitle,
|
title: recurrenceTitle,
|
||||||
startDate: (adjustDays ? startDate.subtract(adjustDays, "hours") : startDate).format("x"),
|
startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"),
|
||||||
endDate: (adjustDays ? endDate.subtract(adjustDays, "hours") : endDate).format("x"),
|
endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"),
|
||||||
fullDayEvent: isFullDayEvent(event),
|
fullDayEvent: isFullDayEvent(event),
|
||||||
recurringEvent: true,
|
recurringEvent: true,
|
||||||
class: event.class,
|
class: event.class,
|
||||||
@ -343,7 +319,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
} else {
|
} else {
|
||||||
// Single event.
|
// Single event.
|
||||||
const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event);
|
const fullDayEvent = isFacebookBirthday ? true : isFullDayEvent(event);
|
||||||
// console.log("full day event")
|
// Log.debug("full day event")
|
||||||
if (includePastEvents) {
|
if (includePastEvents) {
|
||||||
// Past event is too far in the past, so skip.
|
// Past event is too far in the past, so skip.
|
||||||
if (endDate < past) {
|
if (endDate < past) {
|
||||||
@ -376,15 +352,16 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
}
|
}
|
||||||
// if the start and end are the same, then make end the 'end of day' value (start is at 00:00:00)
|
// if the start and end are the same, then make end the 'end of day' value (start is at 00:00:00)
|
||||||
if (fullDayEvent && startDate.format("x") === endDate.format("x")) {
|
if (fullDayEvent && startDate.format("x") === endDate.format("x")) {
|
||||||
//console.log("end same as start")
|
//Log.debug("end same as start")
|
||||||
endDate = endDate.endOf("day");
|
endDate = endDate.endOf("day");
|
||||||
}
|
}
|
||||||
|
// get correction for date saving and dst change between now and then
|
||||||
|
let adjustDays = getCorrection(event, startDate.toDate());
|
||||||
// Every thing is good. Add it to the list.
|
// Every thing is good. Add it to the list.
|
||||||
newEvents.push({
|
newEvents.push({
|
||||||
title: title,
|
title: title,
|
||||||
startDate: startDate.format("x"),
|
startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"),
|
||||||
endDate: endDate.format("x"),
|
endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"),
|
||||||
fullDayEvent: fullDayEvent,
|
fullDayEvent: fullDayEvent,
|
||||||
class: event.class,
|
class: event.class,
|
||||||
location: location,
|
location: location,
|
||||||
@ -406,12 +383,107 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* get the time correction, either dst/std or full day in cases where utc time is day before plus offset
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const getCorrection = function (event, date) {
|
||||||
|
let adjustHours = 0;
|
||||||
|
// if a timezone was specified
|
||||||
|
if (!event.start.tz) {
|
||||||
|
Log.debug(" if no tz, guess based on now");
|
||||||
|
event.start.tz = moment.tz.guess();
|
||||||
|
}
|
||||||
|
Log.debug("initial tz=" + event.start.tz);
|
||||||
|
|
||||||
|
// if there is a start date specified
|
||||||
|
if (event.start.tz) {
|
||||||
|
// if this is a windows timezone
|
||||||
|
if (event.start.tz.includes(" ")) {
|
||||||
|
// use the lookup table to get theIANA name as moment and date don't know MS timezones
|
||||||
|
let tz = getIanaTZFrostart_offset(event.start.tz);
|
||||||
|
Log.debug("corrected TZ=" + tz);
|
||||||
|
// watch out for unregistered windows timezone names
|
||||||
|
// if we had a successfule lookup
|
||||||
|
if (tz) {
|
||||||
|
// change the timezone to the IANA name
|
||||||
|
event.start.tz = tz;
|
||||||
|
// Log.debug("corrected timezone="+event.start.tz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.debug("corrected tz=" + event.start.tz);
|
||||||
|
let current_offset = 0; // offset from TZ string or calculated
|
||||||
|
let mm = 0; // date with tz or offset
|
||||||
|
let start_offset = 0; // utc offset of created with tz
|
||||||
|
// if there is still an offset, lookup failed, use it
|
||||||
|
if (event.start.tz.startsWith("(")) {
|
||||||
|
const regex = /[+|-]\d*:\d*/;
|
||||||
|
const start_offsetString = event.start.tz.match(regex).toString().split(":");
|
||||||
|
let start_offset = parseInt(start_offsetString[0]);
|
||||||
|
start_offset *= event.start.tz[1] == "-" ? -1 : 1;
|
||||||
|
adjustHours = start_offset;
|
||||||
|
Log.debug("defined offset=" + start_offset + " hours");
|
||||||
|
current_offset = start_offset;
|
||||||
|
event.start.tz = "";
|
||||||
|
Log.debug("ical offset=" + current_offset + " date=" + date);
|
||||||
|
mm = moment(date);
|
||||||
|
let x = parseInt(moment(new Date()).utcOffset());
|
||||||
|
Log.debug("net mins=" + (current_offset * 60 - x));
|
||||||
|
|
||||||
|
mm = mm.add(x - current_offset * 60, "minutes");
|
||||||
|
adjustHours = (current_offset * 60 - x) / 60;
|
||||||
|
event.start = mm.toDate();
|
||||||
|
Log.debug("adjusted date=" + event.start);
|
||||||
|
} else {
|
||||||
|
// get the start time in that timezone
|
||||||
|
Log.debug("start date/time=" + moment(event.start).toDate());
|
||||||
|
start_offset = moment.tz(moment(event.start), event.start.tz).utcOffset();
|
||||||
|
Log.debug("start offset=" + start_offset);
|
||||||
|
|
||||||
|
Log.debug("start date/time w tz =" + moment.tz(moment(event.start), event.start.tz).toDate());
|
||||||
|
|
||||||
|
// get the specified date in that timezone
|
||||||
|
mm = moment.tz(moment(date), event.start.tz);
|
||||||
|
Log.debug("event date=" + mm.toDate());
|
||||||
|
current_offset = mm.utcOffset();
|
||||||
|
}
|
||||||
|
Log.debug("event offset=" + current_offset + " hour=" + mm.format("H") + " event date=" + mm.toDate());
|
||||||
|
|
||||||
|
// if the offset is greater than 0, east of london
|
||||||
|
if (current_offset !== start_offset) {
|
||||||
|
// big offset
|
||||||
|
Log.debug("offset");
|
||||||
|
let h = parseInt(mm.format("H"));
|
||||||
|
// check if the event time is less than the offset
|
||||||
|
if (h > 0 && h < Math.abs(current_offset) / 60) {
|
||||||
|
// if so, rrule created a wrong date (utc day, oops, with utc yesterday adjusted time)
|
||||||
|
// we need to fix that
|
||||||
|
adjustHours = 24;
|
||||||
|
// Log.debug("adjusting date")
|
||||||
|
}
|
||||||
|
//-300 > -240
|
||||||
|
//if (Math.abs(current_offset) > Math.abs(start_offset)){
|
||||||
|
if (current_offset > start_offset) {
|
||||||
|
adjustHours -= 1;
|
||||||
|
Log.debug("adjust down 1 hour dst change");
|
||||||
|
//} else if (Math.abs(current_offset) < Math.abs(start_offset)) {
|
||||||
|
} else if (current_offset < start_offset) {
|
||||||
|
adjustHours += 1;
|
||||||
|
Log.debug("adjust up 1 hour dst change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.debug("adjustHours=" + adjustHours);
|
||||||
|
return adjustHours;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* lookup iana tz from windows
|
* lookup iana tz from windows
|
||||||
*/
|
*/
|
||||||
let zoneTable = null;
|
let zoneTable = null;
|
||||||
const getIanaTZFromMS = function (msTZName) {
|
const getIanaTZFrostart_offset = function (msTZName) {
|
||||||
if (!zoneTable) {
|
if (!zoneTable) {
|
||||||
const p = require("path");
|
const p = require("path");
|
||||||
zoneTable = require(p.join(__dirname, "windowsZones.json"));
|
zoneTable = require(p.join(__dirname, "windowsZones.json"));
|
||||||
@ -439,7 +511,7 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
|
|||||||
* @returns {boolean} True if the event is a fullday event, false otherwise
|
* @returns {boolean} True if the event is a fullday event, false otherwise
|
||||||
*/
|
*/
|
||||||
const isFullDayEvent = function (event) {
|
const isFullDayEvent = function (event) {
|
||||||
if (event.start.length === 8 || event.start.dateOnly) {
|
if (event.start.length === 8 || event.start.dateOnly || event.datetype === "date") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user