Datetime helpers for timezone handling
A collection of datetime helpers built on Carbon.
They help you easily parse or convert
DateTimes between timezones (and format them) with one single call., (*2)
A good pattern is to always keep your app working with times in the UTC timezone internally and to store any time data in that default timezone. If you're temped to or already use another timezone as default, please read the following article: Always Use UTC Dates And Times., (*3)
This is how
Carbonator can help you juggle those timezones:, (*4)
Carbonator::parseToDefaultTz($input, $tz_parse = null).
parseToDatetimeLocal($input, $tz_target = null, $tz_parse = null)is one of the methods that can be used to directly format a string for display.
// Create DateTime in any timezone and get it in your app's default timezone: $in_sweden = Carbon::parse('2016-08-07 13:37', 'Europe/Stockholm'); // Stockholm is 2 hours ahead of UTC during daylight savings time $in_utc = Carbonator::parseToDefaultTz($in_sweden); echo $in_utc->toCookieString(); // Sunday, 07-Aug-2016 11:37:00 UTC // Parse directly from a string in a timezone and get it in your app's default timezone: $in_utc = Carbonator::parseToDefaultTz('2016-08-07 13:37', '-05:00'); echo $in_utc->toCookieString(); // Sunday, 07-Aug-2016 18:37:00 UTC // Format a time for a user in Namibia $in_utc = Carbon::parse('2016-08-07 13:37'); // Windhoek is 1 hour ahead of UTC when not on daylight savings time (WAT: West Africa Time) echo Carbonator::formatInTz($in_utc, 'D, M j, Y H:i T', 'Africa/Windhoek'); // Sun, Aug 7, 2016 14:37 WAT // Populate a HTML5 datetime-local input for a user in Japan: $in_utc = Carbon::parse('2016-08-07 13:37'); echo Carbonator::parseToDatetimeLocal($in_utc, 'Asia/Tokyo'); // 2016-08-07T22:37
composer require fewagency/carbonator, (*5)
The Carbon package is excellent,
but it doesn't support parsing other
DateTime instances while keeping their timezone.
That's just the behaviour of the PHP
and not much to do about., (*6)
Carbon throws exceptions on errors.
To be able to parse any user input without having to filter or validate it first,
I wanted wrappers that just returns
null when input can't be parsed., (*7)
I think it makes sense putting these opinionated parsing and display methods into a separate
helper package instead of having
Carbon do even more work., (*8)
Carbonator's methods take a
instance as the first
$input parameter., (*9)
$input will be turned into a
Carbon instance to process.
DateTime and can always be used safely as input., (*10)
$input or any errors in parsing will make methods return
Carbonator's methods also take the
$tz_parse timezone as the last parameter.
$tz_parse timezone will be used as context when parsing an
but will be ignored when parsing
DateTime instances, as they already have a timezone.
As per default
$tz_parse will also be ignored whenever there is timezone
information supplied within the string., (*12)
Timezones can be supplied in
string format (e.g.
'+01:00') or as a
DateTimeZone instance., (*13)
Remember, named timezones like
Europe/Stockholm takes daylight savings time (summer time)
into account, whereas offset timezones like
+01:00 does not.
Use named timezones if you can, your users will appreciate it., (*14)
If a timezone parameter is left out or
null when calling a method,
the PHP default timezone from
will be used., (*15)
Hopefully your default timezone will be
Some frameworks, like Laravel, set the timezone explicitly using a config value
and you should keep that as
UTC unless you really know what you're trying to achieve with
Read more below in Check your setup., (*16)
Carbonator::parse($input, $tz_parse = null)
Note that the timezone of the output doesn't always match the supplied context timezone
from the 2nd parameter. The output is just guaranteed to be
Carbonator::parseToTz($input, $tz_target = null, $tz_parse = null)
Carbon instance, guaranteed to be in the
$tz_target timezone., (*18)
Carbonator::parseToDefaultTz($input, $tz_parse = null)
Carbon instance, guaranteed to be in the PHP default timezone., (*19)
Carbonator::formatInTz($input, $format, $tz_target = null, $tz_parse = null)
Returns a string formatted according to the
$format - see docs for PHP's
The string is guaranteed to be in the
$tz_target timezone., (*20)
Carbonator::parseToDatetimeLocal($input, $tz_target = null, $tz_parse = null)
Returns a string formatted for a
'Y-m-d\TH:i' format (e.g.
'2016-08-07T13:37'), with no timezone information.
Be kind to your users and display the timezone next to your input, perhaps in the
or in an element referenced through the input's
aria-describedby attribute., (*21)
There's no way to know a user's timezone for sure, without asking them.
If you want to help your users select a timezone,
is a nice tool to find relevant timezones by country or continent., (*22)
The list is quite long though, so you could do IP-location on the server side to suggest a timezone to the user. For Laravel there's a package called Laravel Geoip doing just that by connecting to different services., (*23)
In Laravel, there's a handy validation rule for timezone identifiers., (*25)
This console command will check your Linux system timezone:, (*26)
date +%Z, (*27)
This query can be run by MySQL to check which timezones your database is using:, (*29)
SELECT @@global.time_zone, @@session.time_zone
Hopefully both display as
From within PHP you can use
to check what default timezone is used.
If it's not
UTC, find out where it's set by either:, (*31)
If you're using Laravel, you set your app's default timezone in your app's
You can easily check a database-connection's timezone using the
artisan tinker command from the terminal:, (*33)
php artisan tinker, (*34)
Then run:, (*35)
DB::select('SELECT @@global.time_zone, @@session.time_zone');
Again, hopefully both are reported as
If the session timezone is wrong, an optional
'timezone' parameter can be set on MySQL connections
in your app's
Don’t set it manually unless you need to, in which case it should be the same as the
Laravel config, i.e
Actually, pulling in
config('app.timezone') in the database config file works too!, (*36)
Here's a good read on Getting MySQL To Do It when it comes to timezones and PHP., (*37)
I, Björn Nilsved, created this package while working at FEW., (*38)