Appointments time diplayed incorrectly when booked from a different timezone
Closed this issue · 3 comments
Steps to reproduce
Set your calendar to your timezone in my case Pacific/Auckland
Create an appointments calendar.
Register an appointment from another timeone such as Asia/Singapore.
Appoitnment time 8am Singapore time.
The appointment is accepted by the server.
In my calendar shows the Appointment is set at 9pm when the diff between Singapore and Auckland is 5hs. It should show the appointment as 12pm.
Is like if is assuming Singapore is in UTC
Oddly is that the caldav sync also shows the incorrect hour. But I get a notification email at the actual time of the event.
I can consistently replicate this issue with different timezones.
Server time is correct.
Server logtimezone is also correct.
An example in the screenshots
Meeting for 4am Singapore time but shows as 5pm in UI and caldav clients. Notif shows correctly at 9am my time.
Expected behavior
caldav and ui show the right times so you can short your schedules properly
Actual behaviour
makes impossible to knows accurately when your appointments are unless you live by the last minute reminder to attend the events.
Calendar app version
No response
CalDAV-clients used
Thuderbird + DAVx5
Browser
all
Client operating system
all
Server operating system
Ubuntu
Web server
None
Database engine version
None
PHP engine version
None
Nextcloud version
snap 30.0.2
Updated from an older installed version or fresh install
None
List of activated apps
Nextcloud configuration
Web server error log
Log file
Browser log
Additional info
No response
The bookslot does not validate the Timezone of the calendar where the appointment is gonna be added.
https://github.com/nextcloud/calendar/blob/main/lib/Controller/BookingController.php#L155-L200
Something like this:
The start and end timestamps, originally in UTC, are first converted to the booking user's time zone ($userTimeZone). Then, they are converted to the calendar's time zone ($calendarTimeZone)
public function bookSlot(
int $appointmentConfigId,
int $start,
int $end,
string $displayName,
string $email,
string $description,
string $timeZone
): JsonResponse {
// Validate email address
if (!$this->mailer->validateMailAddress($email)) {
return JsonResponse::fail('Invalid email address', Http::STATUS_UNPROCESSABLE_ENTITY);
}
// Ensure start time is before end time
if ($start > $end) {
return JsonResponse::fail('Invalid time range', Http::STATUS_UNPROCESSABLE_ENTITY);
}
// Get the appointment configuration to retrieve the calendar time zone
try {
$config = $this->appointmentConfigService->findById($appointmentConfigId);
$calendarTimeZone = new DateTimeZone($config->getTimeZone());
} catch (ServiceException $e) {
$this->logger->error('No appointment config found for id ' . $appointmentConfigId, ['exception' => $e]);
return JsonResponse::fail(null, Http::STATUS_NOT_FOUND);
}
// Convert start and end times from the booking time zone to the calendar time zone
try {
$userTimeZone = new DateTimeZone($timeZone);
// Convert start time
$startTime = (new DateTimeImmutable('@' . $start))->setTimezone($userTimeZone);
$startTimeInCalendarTz = $startTime->setTimezone($calendarTimeZone)->getTimestamp();
// Convert end time
$endTime = (new DateTimeImmutable('@' . $end))->setTimezone($userTimeZone);
$endTimeInCalendarTz = $endTime->setTimezone($calendarTimeZone)->getTimestamp();
// Book the slot in calendar's time zone
$booking = $this->bookingService->book(
$config,
$startTimeInCalendarTz,
$endTimeInCalendarTz,
$calendarTimeZone->getName(),
$displayName,
$email,
$description
);
} catch (Exception $e) {
$this->logger->error('Time zone conversion error', ['exception' => $e]);
return JsonResponse::fail('Time zone conversion failed', Http::STATUS_INTERNAL_SERVER_ERROR);
}
return JsonResponse::success();
}
Resolved: #6478