Using Custom Patterns with the IntlDateformatter

Displaying custom date and time strings using patterns

By Bob Ray  |  August 4, 2026  |  4 min read
Using Custom Patterns with the IntlDateformatter

In my previous article, . We used the built-in formats (like IntlDateFormatter::FULL). If none of the built-in formats do what you want, you have the option to use the sixth argument to format the date and/or time, though it's almost never the best method. The problem is that when you send a pattern in the sixth argument, that first two arguments, which set the format for the date and time, are ignored completely. That means that whatever pattern you set will be used for all languages. In other words, the IntlDateFormatter class is no longer "locale-aware." As you might guess, if you need a specific date/time format and don't care to internationalize it, you might as well just use PHP's date() function, which is a lot simpler.

There is a way around this, but it's a little finicky. It involves the IntlDatePatternGenerator class.

The IntlDatePatternGenerator Class

The IntlDatePatternGenerator (we'll call it the Generator for short) is designed to solve the problem I mentioned just above. It provides a way to use a custom pattern and still present the date/time in a way that respects the customs in different parts of the globe.

You provide the Generator with a "skeleton" format, consisting of just letters, typically with no spaces or punctuation. You feed the "skeleton" to the Generator and ask it for the best pattern for the current local setting. The Generator computes a new pattern, which you use to format the date/time display.

The code itself is fairly simple, but unlike the built-in formats we saw in my previous article, trying to get things the way you want can sometimes be frustrating.

A Simple Example

Here's some basic code the uses the Generator:

/* Generate a timestamp to use in our example */
$timestamp = strtotime('2025-12-25 04:03:22');

$skeleton = 'yMMMMdHms';

/* Set local and timezone */

$locale = 'en_us';
$timeZone = 'America/Chicago';

// Ask for the best localized pattern for the skeleton
$bestPattern = $patternGenerator->getBestPattern($skeleton)

/* This can be helpful for debugging */
echo "\nReturned pattern for $locale: $bestPattern\n";

/* Use the generated pattern with IntlDateFormatter */
$formatter = new IntlDateFormatter(
    $locale,
    IntlDateFormatter::NONE, // ignored
    IntlDateFormatter::NONE, // ignored
    $timeZone,
    IntlDateFormatter::NULL, // Defaults to Gregorian calendar
    $bestPattern // The generated pattern
);

/* We need a DateTime object for the format() function */
$dateTime = new DateTime();
$dateTime->setTimestamp($timestamp);

/* Single-line version of the two lines above (must use double quotes):
  new DateTime("@$timestamp");
*/

$formattedDate = $formatter->format($dateTime);

echo "Result: $formattedDate\n";

The code above is fairly self-explanatory.

The @ in the single-line version of the call to DateTime() is not the usual PHP error-suppression symbol. It just tells the function that we want to use a timestamp. That's why it has to be enclosed in double quotes.

The official list of all symbols for the skeleton can be found here. It includes some symbols that are only used in "skeleton" patterns for the Generator.

Here is another list that you might fine easier to use. Remember that the "skeleton" should usually have no spaces or punctuation. The Generator does not handle all possible formatting possibilities, so you may have to compromise a little on your preferred format. Unfortunately, I don't know of any way to find out which of the possible formats are supported by the Generator without using a trial-and-error approach. The available formats me change in later versions of PHP. Personally, I'd be inclined to use the built-in format codes from the previous article.

If you really want to geek out, see this page about the Unicode Locale Data Markup Language (LDML)

Coming Up

I tried to make this article as generic as possible, so it could help non-MODX users understand using custom patterns with the IntDateFormatter. In my next article, I'll discuss using the code above to handle MODX date fields.


About Bob Ray

Bob Ray is the author of the MODX: The Official Guide and dozens of MODX Extras including QuickEmail, NewsPublisher, SiteCheck, GoRevo, Personalize, EZfaq, MyComponent and many more. His website is Bob’s Guides. It not only includes a plethora of MODX tutorials but there are some really great bread recipes there, as well.

Learn more about Bob Ray.