One of the most often things to change in web-projects is adapting it to a certain geographical area - language and timezones are two examples. But also there's a date format, which can be pretty different in certain parts of the world. How to handle it properly in Laravel?
1. Blade and jQuery: Form to Add Expenses
Let's say we have a form to add expenses, with DB field expenses.entry_date being stored as a typical DATE with format yyyy-mm-dd, like 1983-01-29. So that's database layer.
But on the front-end side we want our users to operate with US format, which is mm/dd/yyyy, like 01/29/1983.
In our Blade file, first let's add a field, and initialize our jQuery UI Datepicker.
And then we add some JavaScript for jQuery UI Datepicker:
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$( function() {
$('.date').datepicker();
});
</script>
We should see this:
To enforce date format for date picker, all we need to do is add format parameter:
$('.date').datepicker({ format: 'mm/dd/yy' });
To put it more elegantly, let's put it into config/app.php:
[ // ... 'date_format_js' => 'mm/dd/yy', // ... ]
And then use it in Blade:
$('.date').datepicker({ format: '{{ config('app.date_format_js') }}' });
2. Saving the data
Now, if we just submit the form, we will end up with error like this:
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect date value: '07/25/2018' for column 'entry_date' at row 1
Of course, MySQL wants to save date in its native format, which is Y-m-d. So let's transform the value before saving. To do that, we add a mutator method in app/Expense.php model:
public function setEntryDateAttribute($input) { $this->attributes['entry_date'] = Carbon::createFromFormat(config('app.date_format'), $input)->format('Y-m-d'); }
And let's add a new value into our config/app.php:
[ // ... 'date_format' => 'm/d/Y', 'date_format_js' => 'mm/dd/yy', // ... ]
Notice: we have two different config variables because PHP and JavaScript have different rules for formatting dates.
And this way we can make the date save into our database correctly, as 2018-07-25.
3. Viewing/Editing the Date
If you want to show that expense date value in some table, or fill in the edit form, you will get the same format as from database. If you want to transform it, we can add an accessor method into model app/Expense.php:
public function getEntryDateAttribute($input) { return Carbon::createFromFormat('Y-m-d', $input) ->format(config('app.date_format')); }
So in the edit form, you will have something like this:
With this setup, we can easily change the visual format to whatever we want, just by changing values in config/app.php.
But you can go even a step further and save date formats for every user separately, if you need your users to see different formats from different parts of the world. The database will still store it in Y-m-d, you're just playing around with visual presentation of that date.
Useful information:
How to change format for datetime picker input field in Laravel 8 onwards ? Example, in an Appointment form or Schedule form, change time to 24 hours, remove AM/PM and Seconds.
With new Laravel versions - it is
casts
now to cast into dates (instead ofdates
):https://laraveldaily.com/post/laravel-datetime-to-carbon-dates-casts
At the same time, you need new mutators syntax:
https://laravel.com/docs/11.x/eloquent-mutators#accessors-and-mutators