Reputation: 13
Laravel carbon is returning time in UTC when printing Carbon::now()
but doesn't give the correct time while using shiftTimezone
and setTimezone
Below are the results:
Carbon::now(); //"2021-07-20T07:30:29.775871Z"
Carbon::now()->timezoneName; //UTC
Carbon::now()->shiftTimezone('Asia/Kolkata'); //"2021-07-20T02:00:29.452997Z"
Carbon::now()->shiftTimezone('+05:30'); //"2021-07-20T02:00:29.452997Z"
Carbon::now()->shiftTimezone('Asia/Kolkata'); //"2021-07-20T07:30:29.775871Z"
In case of shiftTimeZone, it should add 05:30 hours to the time. But what it actually does is reduces 05:30 from the UTC time. And for setTimezone it is taking the same time as UTC.
Any idea where I'm getting it wrong?
Upvotes: 0
Views: 2374
Reputation: 644
Cannot reproduce the issue with Carbon. Here is my test:
use Carbon\Carbon;
Carbon::now(); // "2023-09-15 01:16:27.000000 UTC (+00:00)"
Carbon::now()->timezoneName; // UTC
Carbon::now()->shiftTimezone('Asia/Kolkata'); // "2023-09-15 01:16:27.000000 Asia/Kolkata (+05:30)"
Carbon::now()->shiftTimezone('+05:30'); // "2023-09-15 01:16:27.000000 +05:30"
Carbon::now()->shiftTimezone('Asia/Kolkata'); // "2023-09-15 01:16:27.000000 Asia/Kolkata (+05:30)"
Carbon::now()->setTimezone('Asia/Kolkata'); // "2023-09-15 06:46:27.000000 Asia/Kolkata (+05:30)"
note:
shiftTimezone
changes the timestamp (points to a different moment)setTimezone
doesn't change the timestamp (still points to the same moment).$d0 = Carbon::parse('2024-01-01 00:00:00');
$d1 = $d0->copy()->setTimezone('America/Los_Angeles');
$d2 = $d0->copy()->setTimezone('Pacific/Niue');
$d0->getTimestamp(); // 1704067200
$d1->getTimestamp(); // 1704067200
$d2->getTimestamp(); // 1704067200
$d0 = Carbon::parse('2024-01-01 00:00:00');
$d1 = $d0->copy()->shiftTimezone('America/Los_Angeles');
$d2 = $d0->copy()->shiftTimezone('Pacific/Niue');
$d0->getTimestamp(); // 1704067200
$d1->getTimestamp(); // 1704096000
$d2->getTimestamp(); // 1704106800
Upvotes: 1
Reputation: 5121
What you put in comments here is not the content of the instance, it's an UTC ISO-8601 string as it's converted to be rendered in JSON output for instance:
echo Carbon::now()->format('Y-m-d H:i:s.u p'); // 2021-07-20 09:36:08.596951 Z
echo Carbon::now()->shiftTimezone('Asia/Kolkata')->format('Y-m-d H:i:s.u p'); // 2021-07-20 09:36:08.596951 +05:30
echo Carbon::now()->shiftTimezone('+05:30')->format('Y-m-d H:i:s.u p'); // 2021-07-20 09:36:08.596951 +05:30
echo Carbon::now()->shiftTimezone('Asia/Kolkata')->format('Y-m-d H:i:s.u p'); // 2021-07-20 09:36:08.596951 +05:30
JSON is converted to UTC because it's a standard way to exchange datetime information, timezone should be a separated information and you only need it to force a timezone, but 99% you want the user/client/browser to use its own timezone so new Date('2021-07-20T09:36:08.596951Z')
in JavaScript or equivalent in other languages will work just fine and apply the current device timezone, which is the correct way for proper localization. Very specific cases where you want to display a date in a timezone that IS NOT the user device timezone, then you should pass "Asia/Kolkata"
explicitly in your JSON output.
Upvotes: 0
Reputation: 4020
In my application, I never use shiftTimezone
or setTimezone
.
I always go with something like the following:
Carbon::now()->timezone('Asia/Kolkata');
It returns me the date in Asia/Kolkata
timezone, without any issue.
Upvotes: 0