Search code examples
javascriptphpangularjsmomentjsangular-moment

Handling UTC dates client side


Here is the situation:

I have occurred_at dates stored in my database in UTC. I'm using laravel to write an API method that returns records that contain these occurred_at fields. They are currently being returned via JSON in a string format (what the PHP Carbon library outputs), ex:

"occurred_at":"2015-04-14 00:25:20" This date "occurred" at 00:25 (12:25 AM) in UTC timezone, but actually at 2015-04-13 17:25 (5:25 PM) in Pacific (PST) timezone.

I am using angular to consume the JSON, and figured I would use the angular-moment library to convert the UTC to local. But it's not working. Both the angular-moment and native angular filters output the same thing:

<span>{{evt.occurred_at | amDateFormat:'L LT'}}</span> <span>{{evt.occurred_at | date:'MM/dd/yyyy @ h:mma'}}</span>

Output:

2015-04-14 00:25:20

Still in UTC. In my angular app code I even have the UTC preprocessor setup to read them in as UTC, but they don't display as local times:

.constant('angularMomentConfig', { preprocess: 'utc' })

There HAS to be a standard way of going about this - storing datetime values in UTC in the database but displaying them as a local time to the user. Do I need make some changes server side? Client side? What is best practice to utilize the "it just works" methods, without writing a ton of code for each date I want to display?

Currently, in non-angular projects, I am using what I consider to be a 'hack' by applying a css class to every span that I want to convert the time to local:

$('.utc-dttm').each(function () {
    var t = moment.utc($(this).text()).local();
    $(this).text(t.format("L") + ' ' + t.format("LT"));
});

But I'd argue this is the wrong way of going about it.


Solution

  • Since a valid JSON datetime string is formatted as ISO-8601 format, you should have Carbon convert the date values to this format before returning it to the client via toIso8601String, like:

    $occurred_at->toIso8601String();
    

    This will output the date string as

    2015-04-14T00:25:20Z
    

    which javascript and any date extension libraries should natively parse as being in UTC timezone and adjust to client timezone when output to user.