From 9d7d838131a1993a9a9486488d68f90b248bbcae Mon Sep 17 00:00:00 2001
From: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Date: Wed, 11 Oct 2023 18:30:35 +0000
Subject: [PATCH] fix: missing last day of month
## What does this PR do?
- Fix that the last day in Oktober was always shown as unavailable
This happened when availability was in Europe/London timezone
- Fix that the last day of November was always shown as unavailable
This happened also for other timezones
## Type of change
- [x] Bug fix (non-breaking change which fixes an issue)
## How should this be tested?
I recommend testing it in staging instead of local, as I experienced some different behaviors on local
- Reproduce the 2 bugs as described before my fix
- If you were able to reproduce it, see if it is fixed with my fixes in this PR (last day of octber and November should be shown as available)
- Check if availability starts and ends at the correct time on days were DST happens
---
packages/features/calendars/DatePicker.tsx | 9 ++++++---
packages/lib/date-ranges.test.ts | 19 +++++++++++++++++++
packages/lib/date-ranges.ts | 11 ++++++++---
3 files changed, 33 insertions(+), 6 deletions(-)
diff --git a/packages/features/calendars/DatePicker.tsx b/packages/features/calendars/DatePicker.tsx
index cf69e33ad4..e046aadcea 100644
--- a/packages/features/calendars/DatePicker.tsx
+++ b/packages/features/calendars/DatePicker.tsx
@@ -92,8 +92,8 @@ const NoAvailabilityOverlay = ({
const { t } = useLocale();
return (
-
-
{t("no_availability_in_month", { month: month })}
+
+
{t("no_availability_in_month", { month: month })}
@@ -139,7 +139,10 @@ const Days = ({
return dates;
};
- const includedDates = currentDate.isSame(browsingDate, "month")
+ const utcBrowsingDateWithOffset = browsingDate.utc().add(browsingDate.utcOffset(), "minute");
+ const utcCurrentDateWithOffset = currentDate.utc().add(browsingDate.utcOffset(), "minute");
+
+ const includedDates = utcCurrentDateWithOffset.isSame(utcBrowsingDateWithOffset, "month")
? availableDates(props.includedDates)
: props.includedDates;
diff --git a/packages/lib/date-ranges.test.ts b/packages/lib/date-ranges.test.ts
index 1e87dd9a56..59a98d886f 100644
--- a/packages/lib/date-ranges.test.ts
+++ b/packages/lib/date-ranges.test.ts
@@ -29,6 +29,25 @@ describe("processWorkingHours", () => {
end: dayjs(`${dateTo.tz(timeZone).format("YYYY-MM-DD")}T21:00:00Z`).tz(timeZone),
});
});
+ it("should have availability on last day of month in the month were DST starts", () => {
+ const item = {
+ days: [0, 1, 2, 3, 4, 5, 6], // Monday to Sunday
+ startTime: new Date(Date.UTC(2023, 5, 12, 8, 0)), // 8 AM
+ endTime: new Date(Date.UTC(2023, 5, 12, 17, 0)), // 5 PM
+ };
+
+ const timeZone = "Europe/London";
+
+ const dateFrom = dayjs().month(9).date(24); // starts before DST change
+ const dateTo = dayjs().startOf("day").month(10).date(1); // first day of November
+
+ const results = processWorkingHours({ item, timeZone, dateFrom, dateTo });
+
+ const lastAvailableSlot = results[results.length - 1];
+
+ expect(lastAvailableSlot.start.date()).toBe(31);
+ });
+
it("should return the correct working hours in the month were DST ends", () => {
const item = {
days: [0, 1, 2, 3, 4, 5, 6], // Monday to Sunday
diff --git a/packages/lib/date-ranges.ts b/packages/lib/date-ranges.ts
index 4fd5cf2f3c..324f82dd08 100644
--- a/packages/lib/date-ranges.ts
+++ b/packages/lib/date-ranges.ts
@@ -23,15 +23,20 @@ export function processWorkingHours({
}) {
const results = [];
for (let date = dateFrom.tz(timeZone).startOf("day"); dateTo.isAfter(date); date = date.add(1, "day")) {
- const dateInTz = date.tz(timeZone);
+ const fromOffset = dateFrom.tz(timeZone).utcOffset();
+ const offset = date.tz(timeZone).utcOffset();
+ // it always has to be start of the day (midnight) even when DST changes
+ const dateInTz = date.add(fromOffset - offset, "minutes").tz(timeZone);
if (!item.days.includes(dateInTz.day())) {
continue;
}
- let start = dateInTz.hour(item.startTime.getUTCHours()).minute(item.startTime.getUTCMinutes()).second(0);
+ let start = dateInTz
+ .add(item.startTime.getUTCHours(), "hours")
+ .add(item.startTime.getUTCMinutes(), "minutes");
- let end = dateInTz.hour(item.endTime.getUTCHours()).minute(item.endTime.getUTCMinutes()).second(0);
+ let end = dateInTz.add(item.endTime.getUTCHours(), "hours").add(item.endTime.getUTCMinutes(), "minutes");
const offsetBeginningOfDay = dayjs(start.format("YYYY-MM-DD hh:mm")).tz(timeZone).utcOffset();
const offsetDiff = start.utcOffset() - offsetBeginningOfDay; // there will be 60 min offset on the day day of DST change