Merge pull request #2634 from jupadin/fixTimeOffset

This commit is contained in:
Michael Teeuw 2021-08-29 14:03:07 +02:00 committed by GitHub
commit 8589d9c482
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 34 deletions

View File

@ -26,6 +26,7 @@ _This release is scheduled to be released on 2021-10-01._
### Fixed ### Fixed
- Fix undefined error with ignoreToday option in weather module (#2620). - Fix undefined error with ignoreToday option in weather module (#2620).
- Fix time zone correction in calendar module when the date hour is equal to the time zone correction value (#2632).
## [2.16.0] - 2021-07-01 ## [2.16.0] - 2021-07-01

View File

@ -138,13 +138,14 @@ const CalendarUtils = {
return CalendarUtils.isFullDayEvent(event) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time])); return CalendarUtils.isFullDayEvent(event) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
}; };
Log.debug("there are " + Object.entries(data).length + " calendar entries"); Log.debug("There are " + Object.entries(data).length + " calendar entries.");
Object.entries(data).forEach(([key, event]) => { Object.entries(data).forEach(([key, event]) => {
Log.debug("Processing entry...");
const now = new Date(); const now = new Date();
const today = moment().startOf("day").toDate(); const today = moment().startOf("day").toDate();
const future = moment().startOf("day").add(config.maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat. const future = moment().startOf("day").add(config.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; let past = today;
Log.debug("have entries ");
if (config.includePastEvents) { if (config.includePastEvents) {
past = moment().startOf("day").subtract(config.maximumNumberOfDays, "days").toDate(); past = moment().startOf("day").subtract(config.maximumNumberOfDays, "days").toDate();
} }
@ -159,10 +160,10 @@ const CalendarUtils = {
} }
if (event.type === "VEVENT") { if (event.type === "VEVENT") {
Log.debug("\nEvent: " + JSON.stringify(event));
let startDate = eventDate(event, "start"); let startDate = eventDate(event, "start");
let endDate; let endDate;
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") {
@ -176,16 +177,21 @@ const CalendarUtils = {
} }
} }
Log.debug(" start=" + startDate.toDate() + " end=" + endDate.toDate()); Log.debug("startDate (local): " + startDate.toDate());
Log.debug("endDate (local): " + 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"));
Log.debug("duration: " + duration);
// FIXME: Since the parsed json object from node-ical comes with time information
// this check could be removed (?)
if (event.start.length === 8) { if (event.start.length === 8) {
startDate = startDate.startOf("day"); startDate = startDate.startOf("day");
} }
const title = CalendarUtils.getTitleFromEvent(event); const title = CalendarUtils.getTitleFromEvent(event);
Log.debug("title: " + title);
let excluded = false, let excluded = false,
dateFilter = null; dateFilter = null;
@ -260,9 +266,13 @@ const CalendarUtils = {
let pastLocal = 0; let pastLocal = 0;
let futureLocal = 0; let futureLocal = 0;
if (CalendarUtils.isFullDayEvent(event)) { if (CalendarUtils.isFullDayEvent(event)) {
Log.debug("fullday");
// if full day event, only use the date part of the ranges // if full day event, only use the date part of the ranges
pastLocal = pastMoment.toDate(); pastLocal = pastMoment.toDate();
futureLocal = futureMoment.toDate(); futureLocal = futureMoment.toDate();
Log.debug("pastLocal: " + pastLocal);
Log.debug("futureLocal: " + futureLocal);
} else { } else {
// if we want past events // if we want past events
if (config.includePastEvents) { if (config.includePastEvents) {
@ -274,9 +284,9 @@ const CalendarUtils = {
} }
futureLocal = futureMoment.toDate(); // future futureLocal = futureMoment.toDate(); // future
} }
Log.debug(" between=" + pastLocal + " to " + futureLocal); Log.debug("Search for recurring events between: " + pastLocal + " and " + futureLocal);
const dates = rule.between(pastLocal, futureLocal, true, limitFunction); const dates = rule.between(pastLocal, futureLocal, true, limitFunction);
Log.debug("title=" + event.summary + " dates=" + JSON.stringify(dates)); Log.debug("Title: " + event.summary + ", with 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,
@ -284,6 +294,7 @@ const CalendarUtils = {
// because the logic below will filter out any recurrences that don't actually belong within // because the logic below will filter out any recurrences that don't actually belong within
// our display range. // our display range.
// Would be great if there was a better way to handle this. // Would be great if there was a better way to handle this.
Log.debug("event.recurrences: " + event.recurrences);
if (event.recurrences !== undefined) { if (event.recurrences !== undefined) {
for (let 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 // Only add dates that weren't already in the range we added from the rrule so that
@ -296,38 +307,42 @@ const CalendarUtils = {
// 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) {
let date = dates[d]; let date = dates[d];
// ical.js started returning recurrences and exdates as ISOStrings without time information. // Remove the time information of each date by using its substring, using the following method:
// .toISOString().substring(0,10) is the method they use to calculate keys, so we'll do the same // .toISOString().substring(0,10).
// (see https://github.com/peterbraden/ical.js/pull/84 ) // since the date is given as ISOString with YYYY-MM-DDTHH:MM:SS.SSSZ
// (see https://momentjs.com/docs/#/displaying/as-iso-string/).
const dateKey = date.toISOString().substring(0, 10); const dateKey = date.toISOString().substring(0, 10);
let curEvent = event; let curEvent = event;
let showRecurrence = true; let showRecurrence = true;
// get the offset of today where we are processing // Get the offset of today where we are processing
// this will be the correction we need to apply // This will be the correction, we need to apply.
let nowOffset = new Date().getTimezoneOffset(); let nowOffset = new Date().getTimezoneOffset();
// for full day events, the time might be off from RRULE/Luxon problem // For full day events, the time might be off from RRULE/Luxon problem
// get time zone offset of the rule calculated event // Get time zone offset of the rule calculated event
let dateoffset = date.getTimezoneOffset(); let dateoffset = date.getTimezoneOffset();
// reduce the time by the offset
// Reduce the time by the following offset.
Log.debug(" recurring date is " + date + " offset is " + dateoffset); Log.debug(" recurring date is " + date + " offset is " + dateoffset);
let dh = moment(date).format("HH"); let dh = moment(date).format("HH");
Log.debug(" recurring date is " + date + " offset is " + dateoffset / 60 + " Hour is " + dh); Log.debug(" recurring date is " + date + " offset is " + dateoffset / 60 + " Hour is " + dh);
if (CalendarUtils.isFullDayEvent(event)) { if (CalendarUtils.isFullDayEvent(event)) {
Log.debug("fullday"); Log.debug("Fullday");
// if the offset is negative, east of GMT where the problem is // If the offset is negative (east of GMT), where the problem is
if (dateoffset < 0) { if (dateoffset < 0) {
// if the date hour is less than the offset // Remove the offset, independently of the comparison between the date hour and the offset,
if (dh < Math.abs(dateoffset / 60)) { // since in the case that *date houre < offset*, the *new Date* command will handle this by
// reduce the time by the offset // representing the day before.
Log.debug(" recurring date is " + date + " offset is " + dateoffset);
// apply the correction to the date/time to get it UTC relative // Reduce the time by the offset:
date = new Date(date.getTime() - Math.abs(nowOffset) * 60000); // Apply the correction to the date/time to get it UTC relative
// the duration was calculated way back at the top before we could correct the start time.. date = new Date(date.getTime() - Math.abs(nowOffset) * 60000);
// fix it for this event entry // the duration was calculated way back at the top before we could correct the start time..
//duration = 24 * 60 * 60 * 1000; // fix it for this event entry
Log.debug("new recurring date1 is " + date); //duration = 24 * 60 * 60 * 1000;
} Log.debug("new recurring date1 is " + date);
} else { } else {
// if the timezones are the same, correct date if needed // if the timezones are the same, correct date if needed
if (event.start.tz === moment.tz.guess()) { if (event.start.tz === moment.tz.guess()) {
@ -348,9 +363,8 @@ const CalendarUtils = {
if (dateoffset < 0) { if (dateoffset < 0) {
// if the date hour is less than the offset // if the date hour is less than the offset
if (dh < Math.abs(dateoffset / 60)) { if (dh < Math.abs(dateoffset / 60)) {
// reduce the time by the offset // Reduce the time by the offset:
Log.debug(" recurring date is " + date + " offset is " + dateoffset); // Apply the correction to the date/time to get it UTC relative
// apply the correction to the date/time to get it UTC relative
date = new Date(date.getTime() - Math.abs(nowOffset) * 60000); 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.. // the duration was calculated way back at the top before we could correct the start time..
// fix it for this event entry // fix it for this event entry
@ -373,6 +387,7 @@ const CalendarUtils = {
} }
} }
startDate = moment(date); startDate = moment(date);
Log.debug("Corrected startDate (local): " + startDate.toDate());
let adjustDays = CalendarUtils.calculateTimezoneAdjustment(event, date); let adjustDays = CalendarUtils.calculateTimezoneAdjustment(event, date);
@ -388,7 +403,7 @@ const CalendarUtils = {
// This date is an exception date, which means we should skip it in the recurrence pattern. // This date is an exception date, which means we should skip it in the recurrence pattern.
showRecurrence = false; showRecurrence = false;
} }
Log.debug("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")) {
@ -408,7 +423,7 @@ const CalendarUtils = {
} }
if (showRecurrence === true) { if (showRecurrence === true) {
Log.debug("saving event =" + description); Log.debug("saving event: " + description);
addedEvents++; addedEvents++;
newEvents.push({ newEvents.push({
title: recurrenceTitle, title: recurrenceTitle,
@ -424,7 +439,7 @@ const CalendarUtils = {
}); });
} }
} }
// end recurring event parsing // End recurring event parsing.
} else { } else {
// Single event. // Single event.
const fullDayEvent = isFacebookBirthday ? true : CalendarUtils.isFullDayEvent(event); const fullDayEvent = isFacebookBirthday ? true : CalendarUtils.isFullDayEvent(event);