Frage und Erwartungen
Während die wörtliche Form dieser Frage im Kontext praktisch ist (Jahr 1899), ist sie im theoretischen Sinne ein wenig vage. Wie alt ist alt Wie weit in die Vergangenheit wollen wir gehen? Was ist mit der Zukunft?
Seit WordPress als Blogging-Engine gestartet ist, hat es sich in diesem Kontext entwickelt, um die folgenden Zeitspannen zu bewältigen:
- Daten WP existierte (offensichtlich in der Lage zu sein, es zu verwenden)
- Auswahl möglicher historischer Beiträge (implizit so lange wie das Internet existiert)
- so weit wie möglich in die Zukunft ohne besonderen Aufwand (arbeiten bis es bricht)
Als sich die Verwendung von WordPress zu nicht-bloggenden Anwendungen entwickelte, begannen solche Projekte (üblicherweise Geschichte und Kunst, wie ich aus Berichten gesehen habe), verschiedene Probleme mit Daten außerhalb dieser Spanne zu lösen.
Für meine Recherche hatte ich folgende Fragen formuliert:
- Was sind die beiden frühesten und spätesten vollen Kalenderjahre, die mit WordPress-Post-Daten nativ und zuverlässig verwendet werden können?
- Was sind niedrig hängende Früchte (falls vorhanden), um die verfügbare Spanne über den einheimischen Bereich hinaus zu erweitern?
Plattformbeschränkungen
Da WordPress eine PHP-Anwendung ist und MySQL zur Datenspeicherung verwendet, unterliegt es deren Einschränkungen.
MySQL
WordPress speichert Datumsangaben in einer post_date
Spalte des DATETIME
Typs in MySQL.
Laut Dokumentation unterstützt dieser Typ die Jahre 1000 bis 9999 :
Der DATETIME
Typ wird für Werte verwendet, die sowohl Datums- als auch Zeitangaben enthalten. MySQL ruft DATETIME
Werte im 'YYYY-MM-DD HH:MM:SS'
Format ab und zeigt sie an . Der unterstützte Bereich ist '1000-01-01 00:00:00'
bis '9999-12-31 23:59:59'
.
Es heißt jedoch auch, dass frühere Werte möglicherweise funktionieren, ohne dass spätere Werte erwähnt werden:
Bei den DATE and DATETIME
Bereichsbeschreibungen bedeutet "unterstützt", dass frühere Werte möglicherweise funktionieren, es jedoch keine Garantie gibt.
Während ich empirisch Werte außerhalb des zulässigen Bereichs beobachtet habe, ist dies anekdotisch und fällt aus unserer Zuverlässigkeitsbedingung heraus.
PHP
In der PHP-Programmierung wird häufig die Unix-Zeitstempeldarstellung des Datums verwendet. Laut Dokumentation für unsere Zwecke (PHP 5.2+ und generische 32-Bit-Umgebung) werden die Jahre (vollständig) 1902 bis 2037 unterstützt :
Der gültige Bereich eines Zeitstempels liegt normalerweise zwischen Fri, 13 Dec 1901 20:45:54 UTC
und Tue, 19 Jan 2038 03:14:07 UTC
. (Dies sind die Daten, die den minimalen und maximalen Werten für eine 32-Bit-Ganzzahl mit Vorzeichen entsprechen.) Darüber hinaus unterstützen nicht alle Plattformen negative Zeitstempel. Daher kann Ihr Datumsbereich auf frühere Werte als die Unix-Epoche beschränkt sein. Dies bedeutet, dass z. B. frühere Daten unter Jan 1, 1970
Windows, einigen Linux-Distributionen und einigen anderen Betriebssystemen nicht funktionieren. PHP 5.1.0 und neuere Versionen überwinden diese Einschränkung.
Abgesehen von dieser neueren VersionDate/Time
ist die Verarbeitung 64-Bit und reicht von ungefähr -292 Milliarden bis 292 Milliarden Jahre , was wahrscheinlich die Bedürfnisse der Menschheit zu diesem Zeitpunkt übersteigt.
Einschränkungen von WordPress
WordPress führt einige zusätzliche Einschränkungen in der Codebasis ein und übernimmt diese.
Datenfluss
Aus der Sicht des grundlegenden Benutzerworkflows gibt es zwei verarbeitete Daten, die sich auf das Datum beziehen:
- Datumseingaben im Nachbearbeitungsformular müssen korrekt verarbeitet und in der Datenbank gespeichert werden
- Das in der Datenbank gespeicherte Datum muss korrekt gelesen und in der Benutzeroberfläche angezeigt werden
Beachten Sie, dass dies technisch völlig unterschiedliche und unabhängige Prozesse sind. Wie weiter unten erläutert, überlappen sich ihre Bereiche nicht und das Speichern des korrekten Datums entspricht nicht der Fähigkeit, es in der WordPress-Umgebung korrekt zu lesen.
Explizite Grenzen
- Der WordPress-Post-Editor in admin ermöglicht einen Zeitraum von 100 bis 9999 Jahren, der als Post-Datum angegeben werden kann
_wp_translate_postdata()
Prozessjahr (als von Formular abweichende Nummer eingereicht) und:
- Desinfiziert es auf nicht negativ > 0
- validiert es mit
wp_checkdate()
, was PHP native aufruft checkdate()
, was ein Limit von 1 bis 32767 auferlegt
Implizite Grenzen
strtotime()
PHP - Funktion wird mehrmals und unterliegt oben genannten Unix - Zeitstempel, auf der untersten Ebene verwendet in , mysql2date()
dass alle von der Datenbank lesen die Daten betrifft, 1902-2037 Bereich geerbt
- WordPress greift bei der Datumsanalyse auf reguläre Ausdrücke zurück, für die
get_gmt_from_date()
das Jahr erwartet wird([0-9]{1,4})
, wobei davon ausgegangen wird , 1 bis 9999 beträgt. Dies ist eine starke Wahrscheinlichkeit für eine ähnliche Verarbeitung in anderen Funktionen, für die eine gründlichere Codeprüfung erforderlich ist
Möglichkeit der Problemumgehung
wp_checkdate()
hat wp_checkdate
Filter, mit dem diese Validierungsprüfung außer Kraft gesetzt werden kann
- Ausgabe an Endbenutzer geht durch
date_i18n()
die hatdate_i18n
Filter, der theoretisch das vollständige Abfangen und erneutes Verarbeiten der Ausgabe von Datumsangaben zur Schnittstelle ermöglicht, jedoch eine Herausforderung, wenn die Funktion bereits außerhalb der range ( false
) - Zeitstempeleingabe übergeben wird
Schlussfolgerungen
Für die praktischen Zwecke und die Portabilität von Daten scheint der Post-Datumsbereich von WordPress dem von 32-Bit-Unix-Zeitstempeln zu entsprechen und besteht aus den Jahren 1902 bis einschließlich 2037 .
Für jede Operation außerhalb dieses Bereichs nach dem Datum muss eine Prüfung durchgeführt werden (64-Bit-Bereich von Unix-Zeitstempeln, de-facto funktionierendes MySQL oder alternativer Datenbankspeicher für die Werte). Für weitere Bereiche ( unter 1000, über 9999) ) sind wahrscheinlich erhebliche Mengen an benutzerdefiniertem Code erforderlich.
Für die Implementierung beliebiger Daten ist es sinnvoll:
- Speichern Sie sie in MySQL in einem Format, das keinen Datenbankbeschränkungen unterliegt
- Verarbeitung in PHP mit vollständig benutzerdefiniertem
Date/Time
Code und / oder WordPress-Funktionen, die geprüft wurden, um nicht von Unix-Zeitstempelbeschränkungen betroffen zu sein
Code-Prüfstand
Der folgende Code und eine handverlesene Reihe von Jahren wurden für die obigen Untersuchungen und die Prüfung der Schlussfolgerungen verwendet:
require ABSPATH . '/wp-admin/includes/post.php';
$timestamp_size_info = array(
'PHP_INT_SIZE' => PHP_INT_SIZE,
'PHP_INT_MAX' => number_format( PHP_INT_MAX ),
'min timestamp' => date( DATE_ISO8601, - PHP_INT_MAX ),
'zero timestamp' => date( DATE_ISO8601, 0 ),
'max timestamp' => date( DATE_ISO8601, PHP_INT_MAX ),
);
r( $timestamp_size_info );
// hand picked set of years to test for assorted limits
$years = array(
'negative' => - 1,
'zero' => 0,
'one' => 1,
'wp min' => 100,
'mysql first' => 1000,
'before unix' => 1899,
'unix first' => 1902,
'current' => 2013,
'unix last' => 2037,
'after unix' => 2039,
'mysql last, wp max' => 9999,
'after checkdate' => 33000,
);
// simulates form submission data
$post = array(
'post_type' => 'post', // shut notice
'edit_date' => 1,
'aa' => 1,
'mm' => '01',
'jj' => '01',
'hh' => '00',
'mn' => '00',
'ss' => '00',
);
// add_filter( 'wp_checkdate', '__return_true' );
foreach ( $years as $name => $year ) {
$post['aa'] = $year;
$translated = _wp_translate_postdata( false, $post );
if ( is_wp_error( $translated ) ) { // wp_checkdate() failed
r( array( 'year' => $year . " ({$name})", 'translated valid' => false ) );
}
else {
$post_date = $translated['post_date'];
$post_date_gmt = $translated['post_date_gmt'];
$translated_valid = (string) $year == substr( $post_date, 0, strpos( $post_date, '-' ) );
$mysql2date = mysql2date( DATE_ISO8601, $post_date );
$mysql2date_valid = (string) $year == substr( $mysql2date, 0, strpos( $mysql2date, '-' ) );
r( array(
'year' => $year . " ({$name})",
'post_date' => $post_date,
'translated valid' => $translated_valid,
'post_date_gmt' => $post_date_gmt,
'mysql2date' => $mysql2date,
'from sql valid' => $mysql2date_valid,
) );
}
}