Arbeiten mit Daten und Zeiten

Zend_Locale_Format bietet verschiedene Methoden für das Arbeiten mit Daten und Zeiten und hilft bei der Konvertierung und Normalisierung zwischen verschiedenen Formaten und verschiedenen Gebietsschemata. Benutzen Sie Zend_Date für die Manipulation von Datumszeichenketten, die bereits übereinstimmen mit einem der vielen international anerkannten Standardformate, oder einem lokalisierten Datumsformat, welche von Zend_Date verwendet werden. Die Verwendung von vordefinierten Formaten bietet Vorteile, wie die Benutzung von gut getestetem Code, und die Sicherheit von Übertragbarkeit und Interoperabilität (abhängig vom benutzten Standard). Das unten angeführte Beispiel folgt nicht dieser Empfehlung, da die Benutzung von nicht standardmäßigen Datumsformaten die Verständlichkeit der Beispiele unnötig vermindern würde.

Daten und Zeiten normalisieren

Die Methode getDate() analysiert Zeichenketten, welche Daten in einem lokalisierten Format enthalten. Das Ergebnis wird als strukturiertes Array zurück gegeben, mit gut definierten Schlüsseln für jeden Teil des Datums. Zusätzlich enthält das Array den Schlüssel 'date_format', der den Format-String enthält, der benutzt wurde um die Zeichenkette mit dem Eingabedatum zu analysieren. Da ein lokalisiertes Datum nicht alle Teile eines Datums oder einer Zeit enthalten muss, sind alle Schlüsselpaare des Arrays optional. Wenn zum Beispiel nur Jahr, Monat und Tag gegeben sind, dann werden alle Zeitwerte beim zurückgegebenen Array unterdrückt und umgekehrt, wenn nur Stunde, Minute und Sekunde als Eingabe angegeben werden. Wenn weder ein Datum noch eine Zeit in der Eingabe gefunden werden, dann wird eine Ausnahme geworfen.

Wenn setOption(array('fix_date' => true)) gesetzt wird, enthält die Methode getDate() einen Schlüssel 'fixed', der eine Zahl enthält, welche anzeigt ob die eingegebene Zeichenkette korrigiert wurde indem Tag, Monat oder Jahr getauscht wurden um in das Format zu passen das angegeben wurde.

Tabelle 104. Schlüsselwerte für getDate() mit der Option 'fix_date'

Wert Bedeutung
0 Nichts korrigiert
1 Falscher Monat wurde korrigiert
2 Tag und Jahr wurden getauscht
3 Monat und Jahr wurden getauscht
4 Monat und Tag wurden getauscht

Für jene die ein spezielles Format für Datumseingaben definieren müssen, werden die nachfolgend angegebenen Formatzeichen unterstützt. Wenn ein ungültiges Formatzeichen verwendet wird, so wie PHPs 'i'-Zeichen in einem ISO-Format, dann wird ein Fehler von den Methoden geworfen, die benutzerdefinierte Formate in Zend_Locale_Format unterstützen.

Die unten angegebenen Zeichen sind nur ein kleiner Teil des kompletten "ISO"-Sets, welches von Zend_Dates toString() unterstützt werden. Wenn PHP date() kompatible Formatzeichen benutzt werden müssen, dann muss zuerst setOptions(array('format_type' => 'php')) aufgerufen werden. Und wenn eine spezielle Formatzeichenkette vom PHP date() kompatiblen Format in ein "ISO"-Format konvertiert werden muss, kann convertPhpToIsoFormat() benutzt werden. Aktuell besteht die einzige praktische Differenz darin, dass das Zeichen für Minuten unterschiedlich ist ('m' wird im ISO-Format und 'i' im date-Format von PHP verwendet).

Tabelle 105. Rückgabewerte

getDate() Formatzeichen Array-Schlüssel Rückgabewert Minimum Maximum
d day Integer 1 31
M month Integer 1 12
y year Integer kein Limit PHPs Maximum für Integer
h hour Integer 0 PHPs Maximum für Integer
m minute Integer 0 PHPs Maximum für Integer
s second Integer 0 PHPs Maximum für Integer

Beispiel 552. Normalisieren von Daten

$dateString = Zend_Locale_Format::getDate(
    '13.04.2006',
    array(
        'date_format' => 'dd.MM.yyyy',
    )
);

print_r($dateString); // Ausgabe:

Array
(
    [date_format] => dd.MM.yyyy
    [locale] => de_DE
    [day] => 13
    [month] => 04
    [year] => 2006
)

// Erstellt ein Zend_Date Objekt für dieses Datum
$dateObject = new Zend_Date('13.04.2006', 'dd.MM.yyyy');

print_r($dateObject); // Ausgabe

Zend_Date Object
(
    [_locale:Zend_Date:private] => de_DE
    [_fractional:Zend_Date:private] => 0
    [_precision:Zend_Date:private] => 3
    [_unixTimestamp:Zend_Date_DateObject:private] => 1144879200
    [_timezone:Zend_Date_DateObject:private] => Europe/Berlin
    [_offset:Zend_Date_DateObject:private] => -3600
    [_syncronised:Zend_Date_DateObject:private] => 0
    [_dst:protected] => 1
)

// Alternativ können einige Arten von Problemen mit
// den Eingabedaten automatisch korrigiert werden
$date = Zend_Locale_Format::getDate(
    '04.13.2006',
    array(
        'date_format' => 'dd.MM.yyyy',
        'fix_date'    => true,
    )
);

print_r($date); // Ausgabe

Array
(
    [date_format] => dd.MM.yyyy
    [locale] => de_DE
    [day] => 13
    [month] => 04
    [year] => 2006
    [fixed] => 4
)

Da getDate() "lokalisierbar" ist, ist die Angabe von $locale ausreichend um Datumseingaben einem Gebietsschemaformat zuzuordnen. Die Option 'fix_date' verwendet einfache Tests um herauszufinden ob Tag oder Monat ungültig sind, um dann eine Heuristik anzuwenden, die versucht alle gefundenen Probleme zu korrigieren. Anzumerken ist auch die Verwendung von 'Zend_Locale_Format::STANDARD' als Wert für 'date_format' bei der Funktion setOptions() um zu verhindern, dass das klassenweit gesetzte standardmäßige Datumsformat verwendet wird. Das zwingt getDate dazu, das standardmäßige Datumsformat dieser $locale zu verwenden.

Beispiel 553. Normalisieren eines Datums durch ein Gebietsschema

$locale = new Zend_Locale('de_AT');
$date = Zend_Locale_Format::getDate('13.04.2006',
                                    array('date_format' =>
                                              Zend_Locale_Format::STANDARD,
                                          'locale' => $locale)
                                   );

print_r ($date);

Ein komplettes Datum mit Uhrzeit wird zurückgegeben, wenn die Eingabe beides, ein Datum und eine Uhrzeit, im erwarteten Format enthält.

Beispiel 554. Normalisieren eines Datums mit Uhrzeit

$locale = new Zend_Locale('de_AT');
$date = Zend_Locale_Format::getDate('13.04.2005 22:14:55',
                                    array('date_format' =>
                                                Zend_Locale_Format::STANDARD,
                                          'locale' => $locale
                                    );

print_r ($date);

Wenn ein spezielles Format gewünscht ist, muss das $format Argument definiert werden, ohne der Angabe von $locale. Nur die einzelnen Zeichen (H, m, s, y, M, d), und MMMM und EEEE werden bei $format unterstützt.

Beispiel 555. Normalisieren eines Benutzerdefinierten Datums

$date = Zend_Locale_Format::getDate('13200504T551422',
                                    array('date_format' =>
                                              'ddyyyyMM ssmmHH')
                                   );

print_r ($date);

Ein Format kann die folgenden Zeichen enthalten:

Tabelle 106. Formatdefinition

Formatbuchstabe Beschreibung
d oder dd Tag mit 1 oder 2 Ziffern
M oder MM Monat mit 1 oder 2 Ziffern
y oder yy Jahr mit 1 or 2 Ziffern
yyyy Jahr mit 4 Ziffern
h Stunde mit 1 oder 2 Ziffern
m Minute mit 1 oder 2 Ziffern
s Sekunde mit 1 oder 2 Ziffern

Beispiele für gültige Formate sind

Tabelle 107. Beispielformate

Formate Eingabe Ausgabe
dd.MM.yy 1.4.6 ['day'] => 1, ['month'] => 4, ['year'] => 6
dd.MM.yy 01.04.2006 ['day'] => 1, ['month'] => 4, ['year'] => 2006
yyyyMMdd 1.4.6 ['day'] => 6, ['month'] => 4, ['year'] => 1

Datumsformate für Datenbanken

Um einen Datumswert einer Datenbank zu analysieren (zum Beispiel MySql oder MsSql) sollte Zend_Dates ISO_8601-Format statt getDate() benutzt werden.

Die Option 'fix_date' benutzt einfache Tests um herauszufinden, ob der Tag oder das Monat ungültig sind, und wendet dann eine Heuristik an, die versucht, die erkannten Probleme zu beheben. getDate() erkennt und behebt automatisch einige Problem mit falschen Eingaben, wie zum Beispiel ein falsch plaziertes Jahr:

Beispiel 556. Automatische Korrektur von Datumsangaben

$date = Zend_Locale_Format::getDate('41.10.20',
                                    array('date_format' => 'ddMMyy',
                                          'fix_date' => true)
                                   );

// Statt 41 für den Tag wird die 41 als Wert für das Jahr zurück gegeben
print_r ($date);

Testen von Daten

checkDateFormat($inputString, array('date_format' => $format, $locale)) kann benutzt werden um zu prüfen, ob eine Zeichenkette alle erwarteten Datumsteile enthält. Die Methode checkDateFormat() benutzt getDate() aber ohne die Verwendung der Option 'fixdate' um zu verhindern, dass TRUE zurück gegeben wird, wenn die Eingabe nicht dem Datumsformat entspricht. Wenn Fehler in der Eingabe gefunden werden, wie zum Beispiel getauschte Werte für Monat oder Jahr, wendet die Option 'fixdate' eine Heuristik an, um das "richtige" Datum zu eruieren, bevor dieses auf Gültigkeit geprüft wird.

Beispiel 557. Testen von Daten

$locale = new Zend_Locale('de_AT');
// Standarddatumsformate für 'de_AT' benutzen... ist es ein gültiges Datum ?
if (Zend_Locale_Format::checkDateFormat('13.Apr.2006',
                                        array('date_format' =>
                                                  Zend_Locale_Format::STANDARD,
                                              $locale)
                                       ) {
    print "Datum";
} else {
    print "kein Datum";
}

Normalisieren von Zeiten

Normalerweise werden Zeiten zusammen mit einem Datum zurückgegeben, wenn die Eingabe beide Werte enthält. Wenn das richtige Format nicht bekannt ist, aber das Gebietsschema für die Eingabe des Benutzers bekannt ist, sollte getTime() verwendet werden, weil es das standardmäßige Zeitformat für das ausgewählte Gebietsschema benutzt.

Beispiel 558. Normalisieren einer unbekannten Zeit

$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::getTime('13:44:42',
                                array('date_format' =>
                                          Zend_Locale_Format::STANDARD,
                                      'locale' => $locale)
                               ) {
    print "Zeit";
} else {
    print "keine Zeit";
}

Testen von Zeiten

checkDateFormat() kann verwendet werden um zu prüfen, ob eine Zeichenkette eine gültige Zeit enthält. Die Verwendung ist genau die gleiche wie beim Prüfen von Daten und date_format sollte die Teile enthalten, die man erwartet.

Beispiel 559. Testen einer Zeit

$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::checkDateFormat('13:44:42',
                                        array('date_format' => 'HH:mm:ss',
                                              'locale' => $locale)) {
    print "Zeit";
} else {
    print "keine Zeit";
}