0

I'm developing a Laravel 6 website with an international focus across various time zones. User comments are being stored in the MySQL database using the default created_at and updated_at UTC timestamps. I retrieve those timestamps in my blade view, e.g. {{ $comment->created_at }}. (On a side note, I use Datatables to display that information among others, so they get wrapped in td). I would like those timestamps to be displayed to the user in his local time.

Upon doing about two hours of research on ways to accomplish that, I did realize that some people suggest retrieving the IP address of the user upon logon and matching that to a geolocation and hence timezone. They would then save that information in the user table of the database and use some PHP function (or Carbon) to translate that into the user's local date/time. I find that solution a bit cumbersome and probably inaccurate. Other people used some method where they end up with specific CSS DIV styles which will then display the user's local time. However, I'm not sure whether that would go well with my use of Datatables. A third potential solution that I looked at was moment.js and it seems to be the cleanest but I'm not sure how this can get implemented, i.e. I was lacking a practical example (I saw somebody asking about the implementation in Vue, but I'm not that skilled yet).

I would therefore like to ask if somebody could please give me an example by showing some code as to how to implement what I would like to achieve in my Laravel project?

Many thanks in advance to everybody!

Ingo T
  • 27
  • 1
  • 7
  • Look at this answer to a similar question: https://stackoverflow.com/a/36148325/5031885 – Pavel Cechir Jul 16 '20 at 07:33
  • If you have not seen it already, take a look at [How to get the exact local time of client](https://stackoverflow.com/questions/10659523/how-to-get-the-exact-local-time-of-client). There are some recent updates to this older question which may help. – andrewJames Jul 16 '20 at 14:03

1 Answers1

1

Thanks for the feedback to @Pavel Cechir and @andrewjames.

After some more digging, I solved it as follows.

Upon user login, I retrieve the local time in login.blade.php through:

@extends('layouts.app')
@section('content')

<form method="POST" action="{{ route('login') }}">
@csrf
<input type="hidden" name="timezone" id="timezone">

...
@endsection

@push('app.js')
<script>
    $(function () {
        // get user timezone
        $('#timezone').val(Intl.DateTimeFormat().resolvedOptions().timeZone)
    })
</script>
@endpush

In LoginController.php, I save the user's timezone into the database:

protected function authenticated(Request $request, $user)
    {
      if ($timezone = $request->get('timezone')) {
        $user->timezone = $request->get('timezone');
        $user->save();
      }
    }

I use the following trait (obtained from https://www.qcode.in/managing-users-timezone-in-laravel-app/):

<?php

namespace App\Traits;

use Carbon\Carbon;

trait HasLocalDates

{

  /**
     * Localize a date to users timezone
     *
     * @param null $dateField
     * @return Carbon
     */
    public function localize($dateField = null)
    {
        $dateValue = is_null($this->{$dateField}) ? Carbon::now() : $this->{$dateField};
        return $this->inUsersTimezone($dateValue);
    }

    /**
     * Change timezone of a carbon date
     *
     * @param $dateValue
     * @return Carbon
     */
    private function inUsersTimezone($dateValue): Carbon
    {
        $timezone = optional(auth()->user())->timezone ?? config('app.timezone');
        return $this->asDateTime($dateValue)->timezone($timezone);
    }

}

And use the trait in the models, e.g. User.php:

use App\Traits\HasLocalDates;

class User extends Authenticatable implements MustVerifyEmail

{
    use Notifiable, HasLocalDates;
...

That way, {{ $comment->created_at }}, {{ $project->updated_at}} etc. will automatically show the user's local date and time.

Ingo T
  • 27
  • 1
  • 7