How do I force PHP's IntlDateFormatter to ignore the year ONLY from the output?

911 views Asked by At

Example code:

$a = new IntlDateFormatter('en-US', IntlDateFormatter::FULL, IntlDateFormatter::NONE, 'Europe/London', IntlDateFormatter::GREGORIAN);
var_dump($a->format(strtotime('2021-09-17 15:00')));

$a = new IntlDateFormatter('sv-SE', IntlDateFormatter::FULL, IntlDateFormatter::NONE, 'Europe/London', IntlDateFormatter::GREGORIAN);
var_dump($a->format(strtotime('2021-09-17 15:00')));

Actual output:

string(26) "Friday, September 17, 2021"
string(24) "fredag 17 september 2021"

Wanted output:

string(26) "Friday, September 17"
string(24) "fredag 17 september"

Changing IntlDateFormatter::FULL to IntlDateFormatter::LONG does not help. It only makes the output like this:

string(18) "September 17, 2021"
string(17) "17 september 2021"

Neither of IntlDateFormatter::NONE, IntlDateFormatter::SHORT and IntlDateFormatter::MEDIUM cause the desired output.

I specifically want the "full" one, but just not the year part.

Please do not suggest any solution which attempts to "hack" away the year, such as string/regexp-removing it. I need the solution to cause the engine to not include the year part in the output. I am sure that other locales have much more complicated/different year parts than the two ones I have used as examples.

2

There are 2 answers

0
Sammitch On

Each locale will define its own date format, and the contents and ordering will vary. Either you need to define a single pattern for all, allow the user to select their desired pattern from a list, or do the thing that you don't seem to want to, and parse/modify the locale's pattern.

There is not an as-is solution that will simply accomplish your desired output automagically.

https://www.php.net/manual/en/intldateformatter.setpattern.php

https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table

$d = new DateTime('2021-09-17 15:00');

$fmt_en = new IntlDateFormatter('en-US', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$fmt_en->setPattern('EEEE, MMMM d');

$fmt_sv = new IntlDateFormatter('sv-SV', IntlDateFormatter::NONE, IntlDateFormatter::NONE);
$fmt_sv->setPattern('MMMM d, EEEE');

var_dump(
    $fmt_en->format($d),
    $fmt_sv->format($d)
);

Output:

string(20) "Friday, September 17"
string(20) "september 17, fredag"
0
Baishu On

Here is what you could do if you only intend to focus on a limited number of locales, and keep a sensible default.

$formatter = match ($lang) {
    'en' => new \IntlDateFormatter($lang, pattern: 'EEEE, MMMM d'),
    'sv' => new \IntlDateFormatter($lang, pattern: 'MMMM d, EEEE'),
    default => new \IntlDateFormatter($lang, \IntlDateFormatter::FULL, \IntlDateFormatter::NONE),
};

$date = $formatter->format($datetime);