In WordPress kann kein altes Datum ausgewählt werden

13

Ich kann das Jahr nicht unter 1899 für einen Posten festlegen. Wenn ich ein Jahr unter 1899 einstelle, wird es automatisch auf das aktuelle Jahr eingestellt.

Bildschirmfoto

Ich habe das Timeline- Theme gekauft und im Support-Forum nachgefragt. Sie antworteten:

Dies klingt wie eine Einschränkung, die von Ihrem Hosting-Anbieter erstellt wurde. Nichts in dem Thema verhindert das Datum, das Sie zuweisen - wie Sie sehen, hat die Demo Beiträge mit Datumsangaben in den 1400er Jahren. Wenden Sie sich an Ihren Hosting-Anbieter, um zu erfahren, wie Sie das beheben können.

Spartaner
quelle
2
Und deine Frage ist was genau? Es gibt Tausende von Themen da draußen - es ist ein langer Weg anzunehmen, dass jemand das Thema kennt, das Sie gekauft haben. Sie müssen mindestens den entsprechenden Code angeben.
Johannes Pille
1
Ich bezweifle, dass es die Schuld des Hosters ist. Ich gehe davon aus, dass es sich um einen in der Datenbank gespeicherten Wert handelt. Aktivieren WP_DEBUGund bearbeiten Sie eine Fehlermeldung in Ihrer Frage. Ich hätte es vielleicht so aussehen lassen, aber ein Link zu einer funktionierenden Version des fraglichen Themas ist auch keine große Hilfe.
Johannes Pille
1
Dies ist eine berechtigte Frage. Es hat nichts mit dem Thema zu tun. Ich kann dieses Problem reproduzieren. Sehen Sie sich diesen animierten Screenshot an .
Fuxia
1
Das gleiche Problem mit 1900 und 1901, aber 1902 funktioniert ;-)
Birgire
1
Ich kann das reproduzieren, es gibt übrigens auch Probleme oberhalb des Unix-Zeitstempelbereichs (2038). PHP 5.4 auf Win7x64
Rarst

Antworten:

10

Dies ist keine wirkliche Antwort, sondern nur ein Versuch, den spezifischen Kontext für dieses Problem zu finden. Bitte installieren Sie das folgende Plugin auf Ihrer Site, versuchen Sie, die drei Daten festzulegen und fügen Sie Ihr Ergebnis zur zweiten <pre>in der folgenden Tabelle hinzu.

/* Plugin Name: WPSE Sysinfo */
add_action( 'admin_footer', 'wpse_sysinfo' );
function wpse_sysinfo() {

    $bit         = 4 === PHP_INT_SIZE ? 32 : 64; // PHP version, not OS!
    $php_version = PHP_VERSION;
    $db_version  = $GLOBALS['wpdb']->db_version();

    print "<pre>$bit | $php_version | $db_version</pre>";
}

Der Inhalt des Plugins kann hier eingesehen werden .

OS | OS-Bit | PHP | PHP Bit | MySQL | 999 | 1899 | 2020 | 2039 | Benutzer
WIN7 | 64 | 5.4.4 | ?? | 5.5.25 | ✘ | ✘ | ✔ | ✘ | toscho
Linux | ?? | 5.3.18-nmm1 | ?? | 5.1.70 | ✔ | ✔ | ✔ | ✔ | toscho
CentOS 6 | 64 | 5.5.4 | ?? | 5.0.95 | ✔ | ✔ | ✔ | ✔ | toscho
WIN7 | 64 | 5.4.15 | 32 | 5.5.31 | ✘ | ✘ | ✔ | ✘ | rarst
Ubuntu 12.04 | 64 | 5.3.10-1 | 64 | 5.5.32 | ✔ | ✔ | ✔ | ✔ | Pille
CloudLinux | 64 | 5.2.17 | 64 | 5.0.96 | ✔ | ✔ | ✔ | ✔ | Pille
Ubuntu 12.10 | 64 | 5.4.6 | 64 | 5.5.32 | ✔ | ✔ | ✔ | ✔ | Michael Ecklund
CENTOS 5.9 | 32 | 5.3.27 | 32 | 5.5.32 | ✘ | ✘ | ✔ | ✘ | Michael Ecklund
WIN7 | 64 | 5.4.7 | 64 | 5.5.27 | ✘ | ✘ | ✔ | ✘ | Kaiser
OSX 10.7.5 | 64 | 5.3.6 | 64 | 5.5.9 | ✔ | ✔ | ✔ | ✔ | GhostToast
Centos 6.4 | 64 | 5.4.17 | 32 | 5.1.59 | ✘ | ✘ | ✔ | ✘ | birgire
Debian 6 | 64 | 5.4.19 | 64 | 5.1.66 | ✘ | ✘ | ✔ | ✘ | birgire
WIN7 | 64 | 5.5.0 | 64 | 5.5.22 | ✘ | ✘ | ✔ | ✘ | GM
OSX 10.7.4 | 64 | 5.3.6 | 64 | 5.5.9 | ✔ | ✔ | ✔ | ✔ | Brasofilo
CentOS 5 | 64 | 5.3.22 | 64 | 5.1.68 | ✔ | ✔ | ✔ | ✔ | Brasofilo
Mac 10.8.5 | 64 | 5.3.26 | 64 | 5.5.25 | ✔ | ✔ | ✔ | ✔ | Flentini
WIN7 | 64 | 5.3.27 | 64 | 5.5.31 | ✔ | ✔ | ✔ | ✔ | Sascha Krause
Win7SP1 | 64 | 5.3.8 | 64 | 5.5.28 | ✔ | ✔ | ✔ | ✔ | Manuel Sychold
  1. Erstellen Sie einen neuen Beitrag. Speichern Sie es.
  2. Stellen Sie das Datum auf den 1. Januar ein 0999und klicken Sie auf Aktualisieren . Wird es gespeichert oder auf das aktuelle Datum geändert?
  3. Wiederholen Sie dies für die Datumseinstellungen für 1899, 2020und 2039.
  4. Übernehmen Sie die Informationen aus der Plugin-Ausgabe in Ihrer Admin-Fußzeile und aktualisieren Sie die Tabelle.
toscho
quelle
7

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:

  1. Was sind die beiden frühesten und spätesten vollen Kalenderjahre, die mit WordPress-Post-Daten nativ und zuverlässig verwendet werden können?
  2. 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_dateSpalte des DATETIMETyps in MySQL.

Laut Dokumentation unterstützt dieser Typ die Jahre 1000 bis 9999 :

Der DATETIMETyp wird für Werte verwendet, die sowohl Datums- als auch Zeitangaben enthalten. MySQL ruft DATETIMEWerte 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 DATETIMEBereichsbeschreibungen 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 UTCund 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, 1970Windows, 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_checkdateFilter, 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/TimeCode 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,
        ) );
    }
}
Rarst
quelle
+1 Nur noch die Frage: Was ist r()?
Kaiser
1
@ Kaiser PHP-Ref , durch Dump-Funktion der Wahl ersetzen :)
Rarst