Question et attentes
Bien que la forme littérale de cette question soit pratique dans son contexte (année 1899), elle est un peu vague au sens théorique. Quel âge a vieux? Jusqu'où peut-on vouloir aller dans le passé ? Qu'en est-il du futur?
Depuis que WordPress avait commencé comme moteur de blog, dans ce sens contextuel , il a évolué pour gérer la période de temps suivante:
- dates d'existence de WP (évidemment pour pouvoir l'utiliser)
- gamme de publications historiques possibles (implicitement aussi loin qu'Internet existait)
- aussi loin dans le futur que possible sans effort particulier (travailler jusqu'à la rupture)
Au fur et à mesure que l'utilisation de WordPress a évolué vers des applications non liées aux blogs, ces projets (généralement l'histoire et l'art comme je l'ai vu dans les rapports) ont commencé à rencontrer des problèmes divers avec des dates en dehors de cette période.
Aux fins de mes recherches, j'avais formulé les questions suivantes:
- Quelles sont les deux premières et dernières années civiles complètes, qui peuvent être utilisées avec les dates de publication WordPress de manière native et fiable?
- Quels sont les fruits à suspension basse (le cas échéant) pour étendre la portée disponible au-delà de l'aire de répartition native?
Limitations de la plateforme
Étant donné que WordPress est une application PHP et utilise MySQL pour le stockage de données, il est soumis à leurs limites.
MySQL
WordPress stocke les dates de publication dans une post_date
colonne de DATETIME
type dans MySQL.
Selon la documentation, ce type prend en charge les années 1000 à 9999 :
Le DATETIME
type est utilisé pour les valeurs qui contiennent des parties de date et d'heure. MySQL récupère et affiche les DATETIME
valeurs au 'YYYY-MM-DD HH:MM:SS'
format. La plage prise en charge est '1000-01-01 00:00:00'
de '9999-12-31 23:59:59'
.
Cependant, il indique également que des valeurs antérieures peuvent fonctionner, aucune mention de valeurs ultérieures:
Pour les DATE and DATETIME
descriptions de plage, «pris en charge» signifie que bien que des valeurs antérieures puissent fonctionner, il n'y a aucune garantie.
Bien qu'empiriquement, j'ai observé des valeurs hors plage de travail, cela est anecdotique et tombe hors de notre condition de fiabilité.
PHP
En programmation PHP, la représentation d'horodatage Unix de la date est largement utilisée. Selon la documentation à nos fins (PHP 5.2+ et environnement générique 32 bits), il prend en charge les années (en entier) 1902 à 2037 :
La plage valide d'un horodatage est généralement de Fri, 13 Dec 1901 20:45:54 UTC
à Tue, 19 Jan 2038 03:14:07 UTC
. (Ce sont les dates qui correspondent aux valeurs minimale et maximale pour un entier signé 32 bits.) De plus, toutes les plates-formes ne prennent pas en charge les horodatages négatifs, par conséquent, votre plage de dates peut être limitée au plus tôt à l'époque Unix. Cela signifie par exemple que les dates antérieures à Jan 1, 1970
ne fonctionneront pas sur Windows, certaines distributions Linux et quelques autres systèmes d'exploitation. PHP 5.1.0 et les versions plus récentes surmontent cependant cette limitation.
En dehors de cette nouvelle Date/Time
gestion basée sur 64 bits, la plage varie entre -292 et 292 milliards d'années , ce qui dépasse probablement les besoins de l'humanité à l'heure actuelle.
Limitations de WordPress
WordPress introduit et hérite de certaines limitations supplémentaires dans sa base de code.
Flux de données
Du point de vue du flux de travail utilisateur de base, deux processus sont liés à la date:
- la date saisie dans le formulaire de post-édition doit être correctement traitée et enregistrée dans la base de données
- la date enregistrée dans la base de données doit être correctement lue et affichée dans l'interface
Notez que ce sont des processus techniquement complètement différents et indépendants. Comme expliqué plus en détail, leurs plages ne se chevauchent pas et la sauvegarde de la date correcte n'équivaut pas à la capacité de la lire correctement dans l'environnement WordPress.
Limites explicites
- L'éditeur de publication WordPress dans admin permet une plage d'années, qui peut être soumise comme date de publication, de 100 à 9999
_wp_translate_postdata()
traite l'année (soumise en tant que numéro distinct du formulaire) et:
- le désinfecte à non négatif > 0
- le valide en utilisant
wp_checkdate()
, qui appelle PHP natif checkdate()
, qui impose une limite de 1 à 32767
Limites implicites
strtotime()
La fonction PHP est utilisée plusieurs fois et est sujette à l'horodatage Unix mentionné ci-dessus, au niveau le plus bas mysql2date()
qui affecte toutes les lectures de dates de la base de données, plage de 1902 à 2037 héritée
- WordPress revient à l'expression régulière pour l'analyse de la date
get_gmt_from_date()
, qui s'attend à ce que l'année soit ([0-9]{1,4})
, en la limitant de 1 à 9999 , une forte possibilité de traitement similaire dans d'autres fonctions qui nécessiteront un audit de code plus approfondi pour être énuméré
Possibilité de contournements
wp_checkdate()
a un wp_checkdate
filtre qui permet de passer outre ce contrôle de validation
- sortie destinée à l' utilisateur final passe par
date_i18n()
qui présente date_i18n
filtre, permet théoriquement d'intercepter et complètement re-sortie processus de dates à l' interface contester si la fonction est passé déjà hors de portée ( false
) entrée d'horodatage
Conclusions
Pour des raisons pratiques et de portabilité des données, la plage de dates de publication WordPress semble être égale à celle de l'horodatage Unix 32 bits et comprend les années 1902 à 2037 inclusivement .
Pour toute opération post-date hors de cette plage, l'environnement doit être audité (plage de 64 bits d'horodatages Unix, MySQL fonctionnant de facto ou stockage de base de données alternatif pour les valeurs). Pour des plages plus éloignées ( inférieures à 1 000, supérieures à 9 999 ), des quantités considérables de code personnalisé seront probablement nécessaires.
Pour toute implémentation de dates arbitraires, il est logique de:
- les stocker dans MySQL dans un format non soumis aux limitations de la base de données
- processus en PHP utilisant du
Date/Time
code entièrement personnalisé et / ou des fonctions WordPress audités pour ne pas être affecté par les limites d'horodatage Unix
Banc d'essai de code
Le code suivant et un ensemble d'années sélectionnées à la main ont été utilisés pour la recherche ci-dessus et pour tester les conclusions:
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,
) );
}
}