简体   繁体   中英

How do I change the date format Laravel outputs to JSON?

I've built an application in Laravel and eloquent returns dates in this format: 2015-04-17 00:00:00 . I'm sending one particular query to JSON so I can make a graph with D3, and I think I would like the dates in ISO8601 ( '1995-12-17T03:24:00' ) or some other format that plays nice with the javascript Date() constructor.

Is there a way to change the date format being output to JSON on the Laravel end? I'm not sure using a mutator is the best approach because it would affect the date in other parts of my application.

Or would it be better to leave the JSON output as is, and use some javascript string methods to manipulate the date format before passing it to the Date() constructor? Which approach is more efficient?

Here is my model:

class Issue extends Model {



protected $fillable = [
    'client_id',
    'do',
    'issue_advocate',
    'service_number',
    'issue_location',
    'issue_description',
    'level_of_service',
    'outcome',
    'referral_id',
    'file_stale_date',
    'date_closed',
    'issue_note',
    'staff_hours'
];

protected $dates = [
    'do',
    'date_closed',
    'file_stale_date'
];

public function setDoAttribute($value)
{
    $this->attributes['do'] = Carbon::createFromFormat('F j, Y', $value)->toDateString();
}
}

Here is my query:

$issues = Issue::with('issuetypes')
->select(['do','level_of_service','outcome','id'])
->whereBetween('do',[$lastyear,$now])
->get()->toJson();

And the JSON I get back:

[{"do":"2014-12-23 00:00:00","level_of_service":1,"outcome":1,"id":18995,"issuetypes":[{"id":9,"issuetype":"Non Liberty","pivot":{"issue_id":18995,"issuetype_id":9}}]}]

I know it's an old question, but there is still no good answer to that. Changing protected $dateFormat will affect database, instead method serializeDate() must be overriden

class MyModel extends Eloquent {
    protected function serializeDate(\DateTimeInterface $date) {
        return $date->getTimestamp();
    }
}

Or myself I chose to create trait

trait UnixTimestampSerializable
{
    protected function serializeDate(\DateTimeInterface $date)
    {
        return $date->getTimestamp();
    }
}

and then add

class SomeClassWithDates extends Model {    
    use UnixTimestampSerializable;

    ...
}

Expanding on umbrel's answer a bit I've created a trait that turns the DateTimeInstance into a Carbon instance so that I can easily make use of it's common formats .

In my particular case I wanted to serialize all dates according to ISO-8601.

The trait is as follows...

use DateTimeInterface;
use Carbon\Carbon;

trait Iso8601Serialization
{
    /**
     * Prepare a date for array / JSON serialization.
     *
     * @param  \DateTimeInterface  $date
     * @return string
     */
    protected function serializeDate(DateTimeInterface $date)
    {
        return Carbon::instance($date)->toIso8601String();
    }

}

and from here I can simply use it on the relevant models...

class ApiObject extends Model
{
    use Iso8601Serialization;
}

Obviously you could name the trait more appropriately if you're using a different format but the point is that you can use any of Carbon's common formats simply by replacing toIso8601String() with the format you need.

I strongly suggest you use the Carbon class to handle all your dates and datetimes variables, it already comes with Laravel 5 so you can start using whenever you want.

Check it out on Carbon Repo to see what you can do with it.

As an example, you can format dates from your model like this

Carbon::parse($model->created_at)->format('d-m-Y')

As for a good approach, I would suggest to use the Repository Pattern along with Presenters and Transformers. By using it you can define how you want your json to be displayed/mounted and opt to skip the presenter whenever you want in order to still get you Eloquent model returned when you make your queries.

You can easily change the format that used to convert date/time to string when your models are serialized as JSON by setting $dateFormat property of your model to the format you need, eg:

class MyModel extends Eloquent {
  protected $dateFormat = 'Y-m-d';
}

You can find docs on different placeholders you can use in the format string here: http://php.net/manual/en/datetime.createfromformat.php

If you use usuals techniques as

protected $dateFormat = 'Y-m-d';

or

protected function serializeDate(DateTimeInterface $date) { ... }

or

protected $casts = [ "myDate" => "date:Y-m-d" ];

It'll only works when laravel will serialize itself objects. And you will anyway to put those code inside all models, for all properties.

So my solution, you have to (too) put this code in all models for all date properties by at last, it works in ALL cases :

public function getMyDateAttribute()
{
    return substr($this->attributes['my_date'], 0, 10);
}

use this function in any Model

protected function serializeDate(DateTimeInterface $date){
    return $date->format('Y-m-d h:i:s');
}

Result

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM