GuavaCZ / calendar

MIT License
140 stars 13 forks source link

[Bug]: Incorrect timezone without the ability to change? #38

Closed HungryBus closed 1 month ago

HungryBus commented 1 month ago

What happened?

Seems like all events are being displayed in the UTC, not my local TZ for some reason.

Amd I doing something wrong?

How to reproduce the bug

Initially, the event start/end times are stored in the DB as a datetime string and getting casted by the Model to Carbon: $casts = ['start' => 'datetime', 'end' => 'datetime'];

This is being picked up by the toEvent() method:

public function toEvent(): array|Event
{
    return Event::make($this)
        ->title($this->event_title)
        ->start($this->start)
        ->end($this->end)
        ->editable(false)
        ->action('view');
}

And despite in CalendarWidget getOptions() determines the locale:

public function getOptions(): array
{
    return ['locale' => 'lv'];
}

And despite the event in the DB is set to Oct 10 2024, for 10:45 to 11:00 and from 11:15 to 11:30, it displays the times by UTC: image image

Forcefully adding 3 hours (that is the difference between .env timezone and UTC) via ->addHours(3) fixes the issue, but is it correct?

Package Version

1.7.0

PHP Version

8.2

Laravel Version

11

Which operating systems does with happen with?

Linux

Notes

No response

lukas-frey commented 1 month ago

The underlying package (vkurko/calendar) doesn't have the ability to change the timezone.

By default, JS uses your browser settings to determine the timezone.

You need to properly handle the dates on the server side, for example via Carbon's shiftTimezone and setTimezone methods.

HungryBus commented 1 month ago

Yeah, shifting timezone to UTC helps, completely forgot about this Carbon method, sorry :)

I know, there's even a feature request for the vkurko/calendar for being able to change timezone, since some browsers are detecting it wrong (and FF sometimes even shifts it with RFP feature.

For any other who's experiencing the same issue:

return Event::make($this)
    ->start($this->start->shiftTimezone('UTC'))
    ->end($this->end->shiftTimezone('UTC'))
    // ...
Graeme-Fitt commented 4 weeks ago

I know this is a limitation of vkurko/calendar, but a solution for this plugin could be to convert the start and end datetime strings received from getEventJs into JS Date objects before returning it to the calendar.

In calendar-widget.js:

return this.$wire.getEventsJs(e).then((events) => {
    events.forEach((event) => {
        event.start = new Date(event.start);
        if ('end' in event) {
            event.end = new Date(event.end);
        }
    })

    return events;
})

If there's anywhere else events are loaded from the backend, then this would need to be used there too, otherwise this would get timezones working properly.

The datetimes are already converted to UTC when being sent to the backend, so no changes are needed there.