Heute habe ich für einen Kunden etwas realisiert, dass mich doch glatt zu einem dritten Artikel zum Thema Datumsangaben mit PHP animiert hat. Wir sind bestimmt alle schon mal auf das Problem gestoßen, dass wir Tage und Monate in deutscher Sprache darstellen müssen. Ich habe es bisher immer so umgesetzt, dass ein Array mit allen Wochentagen und Monaten in jeder benötigten Sprache für die Übersetzung sorgte. Einige Frameworks bieten hier auch komplette Sprach Objekte mit entsprechenden Übersetzungen. Eigentlich ist ein derartiges Vorgehen aber total überflüssig geworden.
IntlDateFormatter ab PHP5.3
Mit PHP5.3 wurde die IntlDateFormatter Klasse als fester Bestandteil von PHP aufgenommen. Ab dieser Version ist es also möglich internationale Datumsformate auszugeben oder zu parsen. Es existiert also eine sehr komfortable Möglichkeit aus einem Thursday einen Donnerstag zu machen. Wir legen nur noch die Zeitzone fest und die IntlDateFormatter Klasse sorgt dafür, dass anhand eines jeden übergebenen Datums ein international angepasstes Format zurückgegeben wird. Folgendes Beispiel verdeutlicht, wie einfach das eigentlich ist.
// Unser aktuelles Datum
$date = new DateTime('2013-02-25');
// Unser internationalisiertes Datum
$formatter = new IntlDateFormatter(
"de-DE",
IntlDateFormatter::LONG,
IntlDateFormatter::NONE,
"Europe/Berlin",
IntlDateFormatter::GREGORIAN,
"EEEE', der' dd. MMMM YYYY"
);
echo $formatter->format($date); // Montag, der 25. Februar 2013
In diesem kurzen Beispiel wird ein Datum als DateTime Objekt erzeugt. Dieses DateTime Objekt übergeben wir dann der format Methode. Bei der Initialisierung der IntlDateFormatter Klasse haben wir schon das Ausgabeformat festgelegt. Es wird also unser DateTime Objekt als „Montag, der 25. Februar 2013“ ausgegeben. Das Format orientiert sich nicht an den von der PHP date() Funktion bekannten Zeichenketten, sondern an einem ISO Format. Dies muss man wissen. Zend stellt auf seiner Seite eine schöne Übersicht des ISO Formats bereit. Ziemlich einfach, oder?
Ein Beispiel aus der Praxis
Für den besagten Kunden musste ich heute ein Auswahlmenü erstellen, welches den Zeitraum von heute bis ein Jahr in die Zukunft als Monate mit Jahreszahlen darstellt. Natürlich sollten die Monate dabei als deutsche Monatsnamen erscheinen. In Teil II zu Datumsangaben mit PHP haben wir bereits die DateInterval und die DatePeriod Klasse kennengelernt. Es bietet sich also direkt an auf Basis dessen eine einfache Schleife zu erstellen, die uns die deutschen Monatsnamen mit den dazugehörigen Jahreszahlen ausgibt.
$formatter = new IntlDateFormatter(
"de-DE",
IntlDateFormatter::FULL,
IntlDateFormatter::NONE,
"Europe/Berlin",
IntlDateFormatter::GREGORIAN,
"MMMM YYYY"
);
$start = new DateTime('2013-02-01');
$end = new DateTime('2014-02-01');
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $month) {
echo $formatter->format($month) . PHP_EOL;
}
// Ausgabe:
// Februar 2013
// März 2013
// April 2013
// Mai 2013
// Juni 2013
// Juli 2013
// August 2013
// September 2013
// Oktober 2013
// November 2013
// Dezember 2013
// Januar 2014
Wie ihr seht, haben wir alle Monatsnamen in deutscher Sprache. Das ging ziemlich einfach, oder?
Tipps und Tricks für XAMPP User
Die Nutzung der Intl Erweiterung ist unter XAMPP nicht standardmäßig aktiviert. Ich stolperte hierüber bei meinen lokalen Tests. Dafür sucht einfach in der php.ini nach dem Eintrag „;extension=php_intl.dll“ und aktiviert diesen, indem ihr einfach das Semikolon davor entfernt. Danach schaut bitte in das Verzeichnis //xampp/php/ und kopiert die Dateien icu*.dll in das Verzeichnis //xampp/apache/bin/. Wenn ihr damit fertig seid, startet den lokalen Server einfach noch mal neu. Es sollte dann funktionieren.
Alternativen zur Intl Erweiterung
PHP bietet neben der Intl Erweiterung auch Funktionen, die die internationalisierte Ausgabe von Datumsformaten ermöglichen. Mit den Funktionen setlocale() und strftime() sind internationalisierte Ausgaben möglich. Allerdings ist eine Funktion wie date() nicht von setlocale() beeinflussbar. Bei setlocale() muss man auch immer darauf achten, wie man die locale Einstellung angibt. Unter Windows lautet die locale Einstellung zum Beispiel „deu“ oder „german“, während Linux Maschinen hier „de_DE“ akzeptieren. Weitere Hinweise sind im PHP Manual zu setlocale() angegeben. Die Liste der Nebenwirkungen scheint hier ein wenig länger zu sein.
Ein kleines Beispiel:
// Unser aktuelles Datum
$date = new DateTime('2013-02-25');
// Unser internationalisiertes Datum
setlocale(LC_ALL, 'de_DE', 'deu', 'german');
echo strftime("%A, der %d. %B %y", $date->format('U')); // Montag, der 25. Februar 13
Fazit
Die Internationalisierung von Datumsangaben ist nicht neu und kann ganz komfortabel genutzt werden. Allerdings spielen hier auch immer die Servereinstellungen eine Rolle. Es soll Maschinen dort draußen geben, die weder setlocale noch die Intl Erweiterung aktiviert haben. Für mich persönlich macht die objektorientierte Klasse IntlDateFormatter mehr Sinn als die setlocale Variante. Allerdings möchte ich die Nutzung hier auch jedem selbst überlassen.