Domanda e aspettative
Mentre la forma letterale di questa domanda è pratica nel contesto (anno 1899) è un po 'vaga in senso teorico. Quanti anni ha? Quanto lontano nel passato potremmo voler andare? E il futuro?
Da quando WordPress era nato come motore di blog, in quel senso contestuale si è evoluto per gestire il seguente arco di tempo:
- date esistenti WP (ovviamente per poterlo usare)
- gamma di possibili post storici (implicitamente fin da quando esisteva Internet)
- il più lontano possibile in futuro senza sforzi particolari (lavorare fino a quando non si rompe)
Man mano che l'utilizzo di WordPress si evolveva in applicazioni non di blog, tali progetti (comunemente storia e arte, come ho visto dai rapporti) hanno iniziato a colpire vari problemi con date al di fuori di questo intervallo.
Ai fini della mia ricerca avevo formulato le seguenti domande:
- Quali sono i due primi e gli ultimi anni del calendario completo, che possono essere utilizzati con le date dei post di WordPress in modo nativo e affidabile?
- Quali sono i frutti pendenti bassi (se presenti) per estendere la portata disponibile oltre la gamma nativa?
Limitazioni della piattaforma
Poiché WordPress è un'applicazione PHP e utilizza MySQL per l'archiviazione dei dati è soggetto ai loro limiti.
MySQL
WordPress memorizza le date dei post nella post_date
colonna di DATETIME
tipo in MySQL.
Secondo la documentazione, questo tipo supporta gli anni da 1000 a 9999 :
Il DATETIME
tipo viene utilizzato per valori che contengono parti di data e ora. MySQL recupera e visualizza i DATETIME
valori in 'YYYY-MM-DD HH:MM:SS'
formato. L'intervallo supportato è '1000-01-01 00:00:00'
quello di '9999-12-31 23:59:59'
.
Tuttavia, dice anche che i valori precedenti potrebbero funzionare, nessuna menzione dei valori successivi:
Per le DATE and DATETIME
descrizioni degli intervalli, "supportato" significa che sebbene i valori precedenti potrebbero funzionare, non esiste alcuna garanzia.
Mentre empiricamente ho osservato valori fuori portata funzionanti, questo è aneddotico e cade fuori dalla nostra condizione di affidabilità.
PHP
Nella programmazione PHP la rappresentazione della data e ora di Unix è ampiamente utilizzata. Secondo la documentazione per i nostri scopi (PHP 5.2+ e ambiente generico a 32 bit) supporta anni (per intero) dal 1902 al 2037 :
L'intervallo valido di un timestamp è in genere da Fri, 13 Dec 1901 20:45:54 UTC
a Tue, 19 Jan 2038 03:14:07 UTC
. (Queste sono le date che corrispondono ai valori minimo e massimo per un intero con segno a 32 bit.) Inoltre, non tutte le piattaforme supportano timestamp negativi, pertanto l'intervallo di date potrebbe essere limitato a non prima dell'epoca di Unix. Ciò significa che, ad esempio, le date precedenti Jan 1, 1970
non funzioneranno su Windows, su alcune distribuzioni Linux e su alcuni altri sistemi operativi. PHP 5.1.0 e le versioni più recenti superano questa limitazione.
A parte questo, la nuova Date/Time
gestione basata su 64 bit è compresa tra -292 e 292 miliardi di anni , il che probabilmente supera le esigenze dell'umanità in questo momento.
Limitazioni di WordPress
WordPress introduce ed eredita alcune limitazioni aggiuntive nella sua base di codice.
Flusso di dati
Dal punto di vista del flusso di lavoro dell'utente di base ci sono due elaborati relativi alla data:
- l'inserimento della data nel modulo di modifica post deve essere correttamente elaborato e salvato nel database
- la data salvata nel database deve essere letta e mostrata correttamente nell'interfaccia
Si noti che si tratta di processi tecnicamente completamente diversi e indipendenti. Come spiegato ulteriormente, i loro intervalli non si sovrappongono e il salvataggio della data corretta non equivale alla capacità di leggerlo correttamente nell'ambiente WordPress.
Limiti espliciti
- L'editor di post di WordPress in admin consente un intervallo di anni, che può essere inviato come data di post, da 100 a 9999
_wp_translate_postdata()
anno dei processi (inviato come numero distinto dal modulo) e:
- lo igienizza in non negativo > 0
- lo convalida usando
wp_checkdate()
, che chiama nativo PHP checkdate()
, che impone un limite da 1 a 32767
Limiti impliciti
strtotime()
La funzione PHP viene utilizzata più volte ed è soggetta al summenzionato timestamp Unix, al livello più basso in mysql2date()
quanto influisce su tutte le letture delle date dal database, intervallo 1902-2037 ereditato
- WordPress ricorre all'espressione regolare per l'analisi della data
get_gmt_from_date()
, che prevede l'anno in corso ([0-9]{1,4})
, limitandolo da 1 a 9999 , forte possibilità di elaborazione simile in altre funzioni che richiederanno un controllo del codice più approfondito per essere enumerati
Possibilità di soluzioni alternative
wp_checkdate()
ha un wp_checkdate
filtro, che consente di ignorare questo controllo di validazione
- l'output rivolto all'utente finale passa attraverso il
date_i18n()
quale ha un date_i18n
filtro, teoricamente consente di intercettare e rielaborare completamente l'output delle date da interfacciare, anche se impegnativo se la funzione viene passata già fuori dall'intervallo di false
timestamp ( )
conclusioni
Ai fini pratici e portabilità dei dati, l'intervallo di date post WordPress sembra essere uguale a quello del timestamp Unix a 32 bit e comprende in modo inclusivo gli anni dal 1902 al 2037 .
Per qualsiasi operazione post-data è necessario controllare l'ambiente al di fuori di questo intervallo (intervallo di 64 bit di timestamp Unix, funzionamento di fatto MySQL o archiviazione di database alternativa per i valori). Per intervalli più lontani ( inferiore a 1000, superiore a 9999 ) è probabile che siano necessarie quantità considerevoli di codice personalizzato.
Per qualsiasi implementazione di date arbitrarie ha senso:
- archiviarli in MySQL in un formato non soggetto alle limitazioni del database
- processo in PHP utilizzando
Date/Time
codice completamente personalizzato e / o funzioni WordPress controllate per non essere influenzate dai limiti di timestamp Unix
Codice banco di prova
Il seguente codice e la serie di anni scelti a mano sono stati usati per la ricerca sopra e il test delle conclusioni:
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,
) );
}
}