Displaying Dates Using User Selected Timezones in Laravel 4

Let me start by saying, you can safely stop worrying about user selected timezones if you are using Laravel 4+. I just spent a few hours trying to determine what was generally the most accepted method to store and display dates using a users own timezone. As it turns out, it is way too easy. So much so that I was finding it difficult to locate up to date Laravel 4 discussions on the topic.

So in case you are as thick as I am, here it is, all spelled out for you.

Important First Step: Set the timezone in app/config/app.php to your preferred timezone (or leave it at UTC if you want) keeping in mind that you will never change this, and you will never do something terrible like Config::set(‘app.timezone’, Auth::user()->timezone); anywhere in your application.

Using the following users table as an example, assume that we want to show foobazed_at to the user using their selected timezone:

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `locale` varchar(255) NOT NULL DEFAULT 'en',
  `timezone` varchar(255) NOT NULL DEFAULT 'America/Toronto',
  `foobazed_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB;

Laravel by default converts created_at, updated_at, and deleted_at columns to instances of Carbon, which, not knowing what Carbon was at the time didn’t mean a whole lot to me. Well, let me tell you… Carbon is awesome.

Instead of doing the following to display the created_at date (which will show the date in the default application timezone):

echo User::find(1)->created_at;

You can simply do this to get created_at in the users own preferred timezone:

echo User::find(1)->created_at->timezone(Auth::user()->timezone);

This is all well and good for the default columns, but what about our foobazed_at date? Easy. In your model (in this case the User model at app/models/User.php) add the following method:

public function getDates()
{
    return array('foobazed_at', static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT);
}

That’s it! Any time you want to display foobazed_at you can simply do this:

echo User::find(1)->foobazed_at->timezone(Auth::user()->timezone);

I hope this is useful to someone else.