Imagine your website has some date input field with date picker. And after you deliver full project, client comes back with request: “By the way, date format should be m/d/y”. Quite a big change in all forms, huh?

So how to prevent this in the very beginning of the project? How to make date format easily configurable, both for database, date picker and in all views?

The biggest problem is that date format is handled in three places:

  • Database should be always YYYY-MM-DD;
  • Laravel back-end: in forms/views we should have whatever format client wants, but while saving to database it should be converted to YYYY-MM-DD;
  • JavaScript datepicker: JS formats for dates are not the same as PHP formats, we will see that below in the example.

So, how to synchronize it all together?
First, let’s make it all work, and later we will make it configurable.

JavaScript Datepicker Format

In this example article, we will use Bootstrap Datepicker as an example.

To make it work, we need these code parts:

<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css" rel="stylesheet" />

...

<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>

<script>
$(document).ready(function () {
  $('.date').datetimepicker({
    format: 'MM/DD/YYYY',
    locale: 'en'
  });
</script>

As you can see, we’re passing the format MM/DD/YYYY which in PHP Date formats would be m/d/Y. Told you about the difference in JavaScript and PHP?

Result is this:


Saving Date to Database

If we POST that form data to some Controller, we get date exactly as it comes from datepicker. And if we try to save it directly to database as m/d/Y, we will get SQL error.

So we need to transform it into the right format. There are a few places we can do it.

Option 1. TransactionController store() method:

public function store(Request $request)
{
    $data = $request->all();
    $data['transaction_date'] = Carbon::createFromFormat('m/d/Y', $request->transaction_date)->format('Y-m-d');
    $transaction = Transaction::create($data);
}

Problem with that approach that you would have to do the same in update() method, and everywhere you need to store that data. Here’s more flexible approach.

Option 2. Model Mutator app/Transaction.php:

public function setTransactionDateAttribute($value)
{
    $this->attributes['transaction_date'] = Carbon::createFromFormat('m/d/Y', $value)->format('Y-m-d');
}

Showing Date in Form/Views

Ok, we saved the date in Y-m-d format in the database. But for users, visually, it always should be m/d/Y. So, similar to the example above, we need to create accessor on the Model.

app/Transaction.php:

public function getTransactionDateAttribute($value)
{
    return Carbon::parse($value)->format('m/d/Y');
}

Read more about mutators and accessors in the official documentation.


Make it configurable

For all the examples above, we need to replace the exact formats with values from config.

So, let’s add these variables to config/app.php:

return [
  'date_format' => 'm/d/Y',
  'date_format_javascript' => 'MM/DD/YYYY',
];

And then, in Laravel, we can use this:

Carbon::createFromFormat(config('app.date_format'), $value)->format('Y-m-d');
Carbon::parse($value)->format(config('app.date_format'));

Finally, we can’t insert variable inside JavaScript, but we can add that script command inside of Blade file, and then we can do this:

  $('.date').datetimepicker({
    format: '{{ config('app.date_format_javascript') }}',
    locale: 'en'
  });

Now, as a full result, if we need to change date format in all project, all we need to do is change variables in config/app.php file.

Did I mention that this is exactly the method that we generate automatically inside of QuickAdminPanel? Try it now!