Laravel 7 - set timezone globaly, save as UTC - laravel

Currently, I have set timezone as Australia/Sydney, (TIMEZONE=Australia/Sydney) and every datetime in DB is saved in this timezone. Is it possible to set timezone globaly, and save as UTC using elouqent?

By default created_at and updated_at are Carbon objects so you can call shiftTimezone('UTC') carbon method on them.

Related

Understand Laravel's timezone

I'm trying to understand the following.
On my config/app.php I'm having my local timezone set to:
'timezone' => 'Europe/Athens'
My Postgres is set to:
SHOW timezone; // returns UTC
In the inserted rows in Postgres i would expect to see my local timezone, converted to UTC. Instead, the timestamp is written on my local timezone.
In another Node.js application, in which I'm working on, with another Postgres instance, when i insert a new row, the local timezone is converted to UTC while the timestamp is stored.
Why this is different on my Laravel app?
What is the case here?

How carbon's timezone are working? How to get date time based on specified timezone?

I'm struggling with the Carbon::now(), I'm specifying the desired timezone in the now function and it is not giving the date time based on the given timezone. It always using the UTC timezone that's specified in the laravel.
Carbon::now() // giving me date time of UTC timezone
Carbon::now('Asia/Karachi') // still giving me the date time of UTC timezone
var_dump(Carbon::now('Asia/Karachi')) // I'm able to see the correct date time based on the timezone.
So when I use the var_dump() I'm getting the correct date time based on the give timezone. Can anyone explain why it is nog returning the correct timezone from the Carbon::now('Asia/Karachi')? but dumping the instance showing the correct datetime.
I've also tried the php artisan cache:clear as well as php artisan config:clear
In config/app.php file change UTC to your desired timezone. It will change app timezone globally.
Eg:
'timezone' => 'Asia/Dhaka',
It always using the UTC timezone
Where? If you're talking about a JSON output, it's expected, date is formatted with ISO-8601 string and a trailing Z meaning Zulu = GMT timezone. The browser or client reading this JSON will have no issue to reconvert it then to any local date time using the user device timezone.
But at anytime if you dump explicitly this instance to a string using any format, the specified timezone will be used:
Carbon::now('Asia/Karachi')->format('Y-m-d H:i:s.u p')
(here using p or e you will see explicitly the timezone in the string.

Laravel WhereDate Filter in Auth User Time zone

My default Laravel application timezone is America/Los_Angeles (pst), I'm storing all the timestamps like created_at with this timezone in database.
In the user profile, we are providing options to select a timezone. While showing the list of data for example in trip listing I'm converting & showing created at as per user selected time zone ( $date->setTimezone($user->timezone);)
For example, if the trip Id 197 has created_at 2020-06-11 23:00:00 stored in db (as per default application timezone i.e. pst) while in the listing I'm showing 2020-06-12 02:00:00 (est timezone as per user profile 3 hrs ahead).
Now everything works fine until I had to add date range (start & end date) filter in the listing. The problem is if I'm selecting start date 2020-10-12 in the filter, in result it is not getting 197 trip id because in the database it is stored as 2020-06-11 23:00:00., this 197 id record should be there in listing after filter because as per auth user timezone the trip is added on 2020-06-12. My DB query is $trips->whereDate('created_at', '>=' ,$request->start_date);. I have the only date and not time in request for filter trips I need to somehow pass timezone in this query or is there any better solution for this. The date filter should work as per user selected timezone
if anyone faced a similar problem following is the answer I found Generally for date range filters you’ll want to make sure you’re setting the start dates time to 00:00 and the end dates time to 23:59
if($request->filled('start_date'))
{
// $request->start_date;
$date = Carbon::parse($request->start_date, auth()->user()->timezone)
->startOfDay()
->setTimezone(config('app.timezone'));
$brokers->where('created_at', '>=' ,$date);
}
if($request->filled('end_date'))
{
$end_date = Carbon::parse($request->end_date, auth()->user()->timezone)
->endOfDay()
->setTimezone(config('app.timezone'));
$brokers->where('created_at', '<=' ,$end_date);
}
When you can have different timezones for 1 column in a table, you need dateTimeTz to store both datetime + timezone for each row.
With this, the whereDate will use the timezone stored, then you can reconvert to any other timezone on need without loss.

Carbon isn't giving the correct datetime with setTimezone

I'm using Carbon inside of my Laravel API project, when trying to set the timezone and get a datetime back in the user's timezone, I'm for some reason getting a UTC value back, what am I doing wrong?
// $user->timezone will give me "America/Curacao" or whatever their time zone is
$curr = Carbon::now()->setTimezone($user->timezone)
But when I echo out the contents of $curr, I'm getting a UTC time of:
2021-04-05T11:58:35.186750Z
What am I missing?
You get the ISO-8601 string with is the standard format for dates in JSON. But the object is correctly in America/Curacao timezone. If you want to pass it to a Date object in the browser, you don't need the timezone and can just pass this string as is.
If you want to format the date to be seen by the user, then just pick the format after setting the timezone:
$curr = Carbon::now()->setTimezone($user->timezone)->format('Y-m-d H:i:s')
Or whatever format would be relevant for you.
And you should keep 'timezone' => 'UTC' in your app settings as your users will likely have any various timezone, and UTC is the more agnostic to use to save them back-end side.

Date comparison not taking timezone into account

I'm trying to compare a start date of an event resource I have with the now date. All dates are being stored as UTC and then the timezone is set according to the user's timezone.
But when I compare the dates the difference is always the same regardless of the timezone I set. It's always being evaluated as UTC. So for instance when I set
$now = Carbon::now()->tz($profileTimezone);
And then try to compare it with another date
$difference = $now->diffInHours($event->starts_at));
It's always returning the same difference object with the same values regardless of the timezone I set for now. Shouldn't the difference in hours, for example, change when now is in a different timezone?
When running the tz method it will convert the datetime object to that timezone. Meaning if you change now to a timezone which is 1 hour behind from the current timezone, it will subtract that hour from the time.
What you are looking for is the method shiftTimezone, that one will change the timezone without changing the time also.
Carbon::now();
// 2019-07-29 12:53:29.575769 UTC (+00:00)
Carbon::now()->shiftTimezone('Asia/Phnom_Penh');
// 2019-07-29 12:53:29.572207 Asia/Phnom_Penh (+07:00)
Carbon::now()->tz('Asia/Phnom_Penh');
// 2019-07-29 19:53:29.575776 Asia/Phnom_Penh (+07:00)

Resources