Mit IntlDateFormatter ein Datum in PHP formatieren

Veröffentlicht am Dienstag, den 13. September 2022

Einführung

Im letzten Artikel wurde mit strtotime() und strftime() ein Datum formatiert. In zukünftigen Versionen ist die Funktion strftime() jedoch veraltet. Deswegen verwenden wir stattdessen den IntlDateFormatter in diesem Artikel.


In PHP kann man ganz einfach einen vorgegebenen String, welches ein Datum enthält, so umwandeln, dass er für einen Nutzer einfach zu lesen ist. Auch kann man damit den Wochentag automatisch bestimmen und sogar die Sprache des formatierten Datums einstellen. Ich gehe davon aus, dass der übergebene String kein sauberer String mit Datum ist, sondern neben dem Datum auch noch weitere Informationen enthält. Diesen gilt es dann vorzubereiten, bevor er in PHP-Funktionen übergeben werden kann.

Funktion

Zuerst schreiben wir eine Funktion format_date, die einen String akzeptiert und das Datum im gewünschten Format zurückgibt.

function format_date($str) {
  $res = preg_match('/(\d{4}-\d{2}-\d{2})/', $str, $matches);
  if (!$res)
    return null;

  $date = date_create($matches[1]);
  $fmt = datefmt_create(
    locale: 'de-DE',
    pattern: 'EEEE, \'den\' d. MMMM y'
    );

  return datefmt_format($fmt,$date);
  }

Gehen wir das Ganze Schritt für Schritt durch.

  1. Mit REGEX wird aus dem übergebenen String das Datum gefiltert. Der gematchte Ausdruck wird in $matches gespeichert. Das Format für das übergebene Datum soll YYYY-MM-DD sein, damit hier was gematcht wird.

  2. Anschließend wird geprüft, dass überhaupt ein zutreffendes Wort gefunden wurde, also ein Datum in dem String. Ist $res 0 oder fehlerhaft, dann geben wir null zurück.

  3. Mit der date_create() Funktion erstellen wir aus dem Wort ein DateTime Objekt. Das werden wir dann im letzten Schritt verwenden.

  4. Neben dem Datum müssen wir ein Format angeben, wie das Datum ausgegeben werden soll. Das machen wir mit dem IntlDateFormatter. Die zwei wichtigsten Parameter hier sind der erste Parameter locale: 'de-DE' und der letzte Parameter pattern: 'EEEE, \'den\' d. MMMM y'.

    Das locale, auf Deutsch Gebietsschema, sagt aus welches Land und welche Sprache verwendet werden soll. Eine komplette Liste der möglichen Werte ist in der ICU Dokumentation zu sehen. Das verändert bei der Ausgabe z.B. die Sprache des Wochentags und des Monats.

    Das pattern gibt die Vorlage für die Ausgabe vor. Schauen wir uns jeden Teil kurz an. Mit EEEE, \'den\' wird der Wochentag gefolgt von einem Komma, Leerzeichen und das Wort den ausgegeben. EEEE steht dabei für den Wochentag völlig ausgeschrieben. Es ist auch E|EE|EEE möglich. Kommata haben keine besondere Bedeutung, genauso wie Leerzeichen. Diese werden einfach so ausgegeben. Anders ist es bei dem Wort 'den'. Damit die Buchstaben nicht interpretiert werden, müssen diese mit einfachen Anführungszeichen ' umschlossen werden. Damit wiederrum der PHP-String nicht vorzeitig beendet wird, werden die Anführungszeichen mit einem \ vorangestellt. Man kann das auch umgehen, indem das Pattern-String mit doppelten, statt einfachen, Anführungszeichen geschrieben wird. Dann werden die \ nicht gebraucht.
    d. MMMM y gibt den Monatstag, gefolgt von einem Punkt, den Monat völlig ausgeschrieben und das Jahr in YYYY Schreibweise. Auch hier sind der Punkt und das Leerzeichen kein Problem. Neben MMMM kann man auch M|MM|MMM geschrieben werden. Wobei bei den ersten beiden Schreibweisen die Zahl des Monats geschrieben wird.
    Die Syntax ist in der ICU Dokumentation geschrieben.

  5. Sind das Format und das Datum bestimmt, kann mit der datefmt_format() Funktion im letzten Schritt das Datum ausgegeben werden. Die Funktion gibt das formatierte Datum als String zurück, welches in unserer Funktion direkt zurückgegeben wird.

Ausgabe

Diese Funktion können wir nun benutzen:

$date = '2022-02-28';
echo format_date($date);
#Ausgabe: Montag, den 28. Februar 2022

Bei 2022-02-28 ist die Ausgabe Montag, den 28. Februar 2022.

Überblick: Uhrzeiten

Wenn man den regulären Ausdruck etwas verändert, und das gewünschte pattern in datefmt_create abändert, kann man auch Uhrzeiten ausgeben. Bei der Eingabe des Strings $str wäre dann sowas wie 2022-02-28-12:22 vorstellbar. Dann matcht man /(\d{4}-\d{2}-\d{2}-\d{2}\:\d{2})/. Das pattern ist dann EEEE, \'den\' d. MMMM y \'um\' H:m \'Uhr\', welches bei der Ausgabe folglich das ausgibt: Montag, den 8. August 2022 um 12:22 Uhr

Fazit

Wie man sehen kann, ist es im Vergleich zum letzten Artikel recht anders. Die wichtigsten Funktionen sind hier datefmt_create() und datefmt_format(). Die Funktionen können explizit angegebene Gebietsschemata verarbeiten und setzen somit weniger auf die globalen PHP-Einstellungen. Ein Vorteil ist z.B. für Unternehmen, die ihre Dienstleistung im Internet global anbieten, besser auf die unterschiedlichen Sprachen ihrer Nutzer eingehen können. Man verändert nicht mehr global irgendwelche Einstellungen, sondern nur für den einen Fall die gewünschte Ausgabe. Das ist auch gerade für Mehrbenutzersynchronisation besser, da nicht mehr irgendwann und irgendwo das Gebietsschema geändert wird.