Fix off-by-one calendar months with time zones that are greater than UTC+0 (#86)

Fix off-by-one calendar months with time zones that are greater than UTC+0 (GMT+0).

Fix https://github.com/matrix-org/matrix-public-archive/issues/77

Previously, we would calculate `lastDayOfTheMonthDate` in the local timezone because we were using the vanilla `new Date(year, month, 0)` constructor. For any timezone greater than `UTC+0` (like London UTC+1 or Korea UTC +9), this means that the date is a day-behind when we go back to UTC+0.

**Before:**

```
inputDate Fri, 29 Jul 2022 00:00:00 GMT 1659052800000
lastDayOfTheMonthDate Sat, 30 Jul 2022 23:00:00 GMT 1659222000000
lastDayOfTheMonth 30
```

**After**

```
inputDate Fri, 29 Jul 2022 00:00:00 GMT 1659052800000
lastDayOfTheMonthDate Sun, 31 Jul 2022 00:00:00 GMT 1659225600000
lastDayOfTheMonth 31
```
This commit is contained in:
Eric Eastwood 2022-10-18 18:36:13 -05:00 committed by GitHub
parent df89750401
commit f9e16964e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 12 additions and 6 deletions

View File

@ -12,13 +12,18 @@ function sameDay(date1, date2) {
); );
} }
// Month in JavaScript is 0-indexed (January is 0, February is 1, etc), // Get the number of days in the given month where the `inputDate` lies.
// but by using 0 as the day it will give us the last day of the prior
// month.
// //
// via https://stackoverflow.com/a/1184359/796832 // via https://stackoverflow.com/a/1184359/796832
function numDaysInMonthForDate(date) { function numDaysInMonthForDate(inputDate) {
return new Date(date.getUTCFullYear(), date.getUTCMonth() + 1, 0).getUTCDate(); // Month in JavaScript is 0-indexed (January is 0, February is 1, etc),
// but by using 0 as the day it will give us the last day of the prior
const lastDayOfTheMonthDate = new Date(
Date.UTC(inputDate.getUTCFullYear(), inputDate.getUTCMonth() + 1, 0)
);
const lastDayNumberOfTheMonth = lastDayOfTheMonthDate.getUTCDate();
// The last day number in the month is a proxy for how many days there are in that month
return lastDayNumberOfTheMonth;
} }
// Map from day of week to the localized name of the day // Map from day of week to the localized name of the day
@ -147,9 +152,10 @@ class CalendarView extends TemplateView {
}), }),
(() => { (() => {
const todayTs = Date.now(); const todayTs = Date.now();
const numberOfDaysInMonth = numDaysInMonthForDate(calendarDate);
let dayNodes = []; let dayNodes = [];
for (let i = 0; i < numDaysInMonthForDate(calendarDate); i++) { for (let i = 0; i < numberOfDaysInMonth; i++) {
const dayNumberDate = new Date(calendarDate); const dayNumberDate = new Date(calendarDate);
// Date is a 1-based number // Date is a 1-based number
dayNumberDate.setUTCDate(i + 1); dayNumberDate.setUTCDate(i + 1);