Locale-aware Date and Time Formatting in PHP 5.3

February 7, 2012

In the third edition of my “PHP and MySQL for Dynamic Web Sites: Visual QuickPro Guide” book, titled “[intlink id=”1582″ type=”page”]PHP 6 and MySQL 5 for Dynamic Web Sites: Visual QuickPro Guide[/intlink]”, I went out on a limb and used a beta version of PHP 6 when writing the book. PHP 6 was about half-way done at the time, and I didn’t want to complete the book, only to have it be outdated immediately thereafter (using PHP 6 wasn’t, by the way, an attempt to trick the reader into buying the book, as some cynical people have suggested). Well…[intlink id=”1067″ type=”post”]PHP 6 ended up dying due to many complications[/intlink] and I had the proverbial egg on my face (what one reader rightfully called my “Dewey Defeats Truman” moment). In truth, only about 5% of the book or so required PHP 6, so it wasn’t a devastating mistake, but I certainly felt foolish.

One of the things I wanted to cover in PHP 6 was locale-aware date and time formatting, as part of the goal of PHP 6 was to recognize the more global Web environment. Even though PHP 6 was shelved, the key components have since been integrated into PHP 5.2, 5.3, and the forthcoming 5.4. Locale-aware date and time formatting was demonstrated in the book using the PHP 6 date_format_locale() function. That function went belly-up, and PHP 5.3 now has the IntlDateFormatter class instead. The documentation for the class in poor, but here’s what I figured out…

First, let’s look at the original script, Script 14.5, locales.php:

// Set the default timezone:
date_default_timezone_set('UTC');

// Need a date object:
$d = new DateTime();

// Create a list of locales:
$locales = array('en_US', 'fr_FR', 'es_BO', 'zh_Hans_CN', 'ru_RU', 'el_GR', 'is_IS');

// Print the date in each locale:
foreach ($locales as $locale) {

    // Set the locale:
    locale_set_default($locale);

    // Print the date:
    echo "<p>$locale: " . strtotitle(date_format_locale($d, 'l, j F Y')) . "</p>\n";

}

To convert this to work with the IntlDateFormatter class in PHP 5.3, the list of locales must first be changed to use hyphens instead of underscores:

$locales = array('en-US', 'fr-FR', 'es-BO', 'zh-Hans-CN', 'ru-RU', 'el-GR', 'is-IS');

Then, the code for setting the local and formatting the date using that locale (both lines within the loop) have to be changed. As with many things in PHP, you can use the IntlDateFormatter class as an object or procedurally. Let’s look at the procedural approach first, which is what the book also does.

The first step is to create an IntDateFormatter object, using datefmt_create(). Its first argument is the locale. Its next two arguments, both of which are required, are constants representing the date format and the time format. Those constants are listed in the manual. Here’s the complete function call, which would go first within the loop:

$fmt = datefmt_create($locale, IntlDateFormatter::LONG, IntlDateFormatter::SHORT);

That variable will be used as the first argument in the datefmt_format() function. The second argument to the function is the date and time, represented as a DateTime object:

echo "<p>$locale: " . datefmt_format($fmt, $d) . "</p>\n";

Here is the resulting output:

The date and time represented using different locales.

To do the same thing using OOP, you would write:

$ftm = new IntlDateFormatter($locale, IntlDateFormatter::LONG, IntlDateFormatter::SHORT);

$ftm->format($d);

And there you have it!