DatePicker subtracts one day when using timezone
Package
filament/filament
Package Version
v3.2.137
Laravel Version
v11.41.3
Livewire Version
v3.5.12
PHP Version
8.3.4
Problem description
This is the input:
public static function starts(): DatePicker
{
return DatePicker::make('starts_at')
->label(__('Starts at'))
->required()
->live()
->seconds(false)
->timezone('Europe/Amsterdam');
}
This is the model caster:
class Ticket extends Model
{
/**
* @var array<string, string>
*/
protected $casts = [
'starts_at' => 'date:Y-m-d',
];
}
When the filled date is 10-02-2025, and you save model changes, it will be saved as 09-02-2025 (day-1). This happens on every save,even when setting a different date.
I know bugs reports exists, but even after appyling the date casting it still happens: https://github.com/filamentphp/filament/issues/5601#issuecomment-1680371753
Removing the timezone method fixes the issue, it also work fine when you set ->timezone('UTC') (same timezone as application). But we need this conversion for international users, and we keep the application as UTC.
If you need more debug information, please let me know.
Thanks.
Expected behavior
Timezone method working
Steps to reproduce
- Create datepicker input
- Set
->timezone('x') - Submit form
Reproduction repository (issue will be closed if this is not valid)
https://github.com/francoism90/filament-dateinput-timezone
Relevant log output
I don't have a log, if you need a value dump, please let me know.
What may be relevant is that the actual database column is datetime (timestamp). At the moment only dates are required, time will be added later. It's fine this is stored as 00:00:00.
Could this be the problem?
Yes, I have the same issue as well.
Fairly sure this is because of Daylight saving and your db timezone. so therefore when saving it is saving at the correct date.
I filled the Blog Post published_at attribute with 10-10-1973 and gave the timezone to Asia/Dhaka and created a new Blog Post with the instructions in Step to Reproduce (creating a publishes() method with the above code snippet) and reviewed the changes in published_at in the newly created blog post. It's showing the same date:
this issue exists when we use local timezone
when app using UTC and set the field using local timezone. it will save using local timezone value. thats why there is difference
fixed it with this
protected function setFilamentFieldTimezone(string $timezone): void
{
/*
* configure field timezone only when displaying
*/
DatePicker::configureUsing(function (DatePicker $datePicker) use ($timezone): void {
if ($datePicker->isReadOnly()) {
$datePicker->timezone($timezone);
}
});
/*
* configure field timezone only when displaying
*/
DateTimePicker::configureUsing(function (DateTimePicker $dateTimePicker) use ($timezone): void {
if ($dateTimePicker->isReadOnly()) {
$dateTimePicker->timezone($timezone);
}
});
TextColumn::configureUsing(function (TextColumn $textColumn) use ($timezone): void {
if ($textColumn->isDateTime() || $textColumn->isDate()) {
$textColumn->timezone($timezone);
}
});
}```
This issue is because the "timezone" feature only really makes sense when using date-times or times, not date-only. Date only is storing a date with a "midnight" time, and midnight in Amsterdam is always the next day to UTC, hence why the day is stored as the day before.
I don't think this specifically is a bug in Filament, we are storing the correct midnight date in UTC based on the timezone you give us.
I do not think you need to use the timezone method at all for non-timed dates, if you are never expecting the date to be stored differently to how the user inputs it.
Please let me know if I'm missing something and I can reopen