No se puede seleccionar una fecha anterior en WordPress

13

No puedo establecer el año por debajo de 1899 para una publicación. Si configuro el año por debajo de 1899, se establece automáticamente en el año actual.

captura de pantalla

Compré el tema de la línea de tiempo y pregunté en su foro de soporte. Ellos respondieron:

Esto suena como una limitación creada por su proveedor de alojamiento. No hay nada en el tema que impida la fecha que asigna: como puede ver, la demostración tiene publicaciones que usan fechas en la década de 1400. Intente ponerse en contacto con su proveedor de alojamiento y vea si tienen alguna idea sobre cómo abordar eso.

Espartanos
fuente
2
¿Y tu pregunta es qué exactamente? Hay miles de temas por ahí, es muy difícil suponer que alguien conocerá el tema que compraste. Al menos deberás proporcionar un código relevante.
Johannes Pille
1
Dudo que sea culpa del huésped. Supongo que se trata de un valor guardado en la base de datos. Encienda WP_DEBUGy edite un mensaje de error en su pregunta. Podría haberlo hecho parecer así, pero un enlace a una versión funcional del tema en cuestión tampoco ayuda mucho.
Johannes Pille
1
Esta es una pregunta legítima. No está relacionado con el tema. Puedo reproducir este problema Vea esta captura de pantalla animada .
fuxia
1
El mismo problema con 1900 y 1901 pero 1902 funciona ;-)
birgire
1
Puedo reproducir esto, por cierto, también hay problemas por encima del rango de marca de tiempo de Unix (2038). PHP 5.4 en Win7x64
Rarst

Respuestas:

10

Esto no es realmente una respuesta, solo un intento de encontrar el contexto específico para este problema. Instale el siguiente complemento en su sitio, intente establecer las tres fechas y agregue su resultado al segundo <pre>en la tabla a continuación.

/* 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>";
}

Gist of the Plugin se puede consultar aquí .

OS | Bit OS | PHP | Bit PHP | MySQL | 999 1899 2020 | 2039 | usuario
WIN7 | 64 5.4.4 | ?? El | 5.5.25 | ✘ | ✘ | ✔ | ✘ | toscho
Linux | ?? El | 5.3.18-nmm1 | ?? El | 5.1.70 | ✔ | ✔ | ✔ | ✔ | toscho
CentOS 6 | 64 5.5.4 | ?? El | 5.0.95 | ✔ | ✔ | ✔ | ✔ | toscho
WIN7 | 64 5.4.15 | 32 5.5.31 | ✘ | ✘ | ✔ | ✘ | más raro
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 | ✘ | ✘ | ✔ | ✘ | emperador
OSX 10.7.5 | 64 5.3.6 | 64 5.5.9 | ✔ | ✔ | ✔ | ✔ | Tostada fantasma
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. Crea una nueva publicación. Guárdalo
  2. Establezca la fecha en 1 de enero 0999, haga clic en Actualizar . ¿Se guarda o cambia a la fecha actual?
  3. Repita para los ajustes de fecha para 1899, 2020y 2039.
  4. Tome la información de la salida del complemento en su pie de página de administrador y actualice la tabla.
toscho
fuente
7

Pregunta y expectativas

Si bien la forma literal de esta pregunta es práctica en su contexto (año 1899), es un poco vaga en sentido teórico. ¿Qué edad tiene edad? ¿Qué tan lejos en el pasado podríamos querer llegar? ¿Qué pasa con el futuro?

Desde que WordPress comenzó como motor de blogs, en ese sentido contextual evolucionó para manejar el siguiente período de tiempo:

  • fechas en que WP existió (obviamente para poder usarlo)
  • gama de posibles publicaciones históricas (implícitamente desde Internet)
  • Lo más lejos posible en el futuro sin un esfuerzo especial (trabajar hasta que se rompa)

A medida que el uso de WordPress evolucionó hacia aplicaciones que no son de blogs, tales proyectos (comúnmente historia y arte, como he visto en los informes) comenzaron a atacar varios problemas con fechas fuera de este lapso.

A los fines de mi investigación, formulé las siguientes preguntas:

  1. ¿Cuáles son los dos primeros y más completos años calendario completos, que se pueden usar con las fechas de publicación de WordPress de forma nativa y confiable?
  2. ¿Qué son las frutas bajas (si las hay) para extender el alcance disponible más allá del rango nativo?

Limitaciones de la plataforma

Dado que WordPress es una aplicación PHP y usa MySQL para el almacenamiento de datos, está sujeto a sus limitaciones.

MySQL

WordPress almacena las fechas de publicación en una post_datecolumna de DATETIMEtipo en MySQL.

Según la documentación, este tipo admite los años 1000 a 9999 :

El DATETIMEtipo se utiliza para valores que contienen partes de fecha y hora. MySQL recupera y muestra DATETIMEvalores en 'YYYY-MM-DD HH:MM:SS'formato. El rango admitido es '1000-01-01 00:00:00'a '9999-12-31 23:59:59'.

Sin embargo, también dice que los valores anteriores podrían funcionar, sin mencionar los valores posteriores:

Para las DATE and DATETIMEdescripciones de rango, "compatible" significa que aunque los valores anteriores podrían funcionar, no hay garantía.

Si bien empíricamente he observado valores fuera de rango, esto es anecdótico y cae fuera de nuestra condición de confiabilidad.

PHP

En la programación PHP, la representación de fecha y hora de Unix es ampliamente utilizada. De acuerdo con la documentación para nuestros fines (PHP 5.2+ y entorno genérico de 32 bits) es compatible con años (en su totalidad) 1902 a 2037 :

El rango válido de una marca de tiempo es típicamente de Fri, 13 Dec 1901 20:45:54 UTCa Tue, 19 Jan 2038 03:14:07 UTC. (Estas son las fechas que corresponden a los valores mínimos y máximos para un entero con signo de 32 bits). Además, no todas las plataformas admiten marcas de tiempo negativas, por lo tanto, su rango de fechas puede estar limitado a no antes de la época de Unix. Esto significa que, por ejemplo, las fechas anteriores Jan 1, 1970no funcionarán en Windows, algunas distribuciones de Linux y algunos otros sistemas operativos. Sin embargo, PHP 5.1.0 y las versiones más nuevas superan esta limitación.

Además de ese Date/Timemanejo basado más nuevo, es de 64 bits y tiene un rango de aproximadamente -292 mil millones a 292 mil millones de años , lo que probablemente excede las necesidades de la humanidad en este momento.

Limitaciones de WordPress

WordPress presenta y hereda algunas limitaciones adicionales en su base de código.

Flujo de datos

Desde el punto de vista del flujo de trabajo básico del usuario, hay dos procesados ​​relacionados con la fecha:

  • La entrada de fecha en el formulario de edición posterior debe procesarse correctamente y guardarse en la base de datos
  • la fecha guardada en la base de datos debe leerse correctamente y mostrarse en la interfaz

Tenga en cuenta que estos son procesos técnicamente completamente diferentes e independientes. Como se explicó más adelante, sus rangos no se superponen y guardar la fecha correcta no equivale a la capacidad de leerlo correctamente en el entorno de WordPress.

Límites explícitos

  • El editor de publicaciones de WordPress en administración permite un rango de años, que se pueden enviar como fecha de publicación, 100 a 9999
  • _wp_translate_postdata() procesa el año (presentado como un número distinto del formulario) y:
    • lo desinfecta a no negativo > 0
    • lo valida usando wp_checkdate(), que llama PHP nativo checkdate(), que impone un límite de 1 a 32767

Límites implícitos

  • strtotime()La función PHP se usa varias veces y está sujeta a la marca de tiempo Unix mencionada anteriormente, en el nivel más bajo mysql2date()que afecta a todas las lecturas de fechas de la base de datos, rango heredado de 1902 a 2037
  • WordPress recurre a la expresión regular para el análisis de fechas get_gmt_from_date(), que espera que el año sea ([0-9]{1,4}), limitando de 1 a 9999 , una fuerte posibilidad de procesamiento similar en otras funciones que requerirán una auditoría de código más exhaustiva para enumerarse

Posibilidad de soluciones alternativas

  • wp_checkdate()tiene wp_checkdatefiltro, que permite anular esta verificación de validación
  • la salida dirigida al usuario final atraviesa date_i18n()y tiene date_i18nfiltro, teóricamente permite interceptar y reprocesar completamente la salida de fechas para la interfaz, sin embargo, es un desafío si la función ya se pasa fuera de rango ( false) entrada de marca de tiempo

Conclusiones

A efectos prácticos y de portabilidad de datos, el intervalo de fechas de publicación de WordPress parece ser igual al de la marca de tiempo Unix de 32 bits y consta de los años 1902 a 2037 inclusive .

Para cualquier operación posterior a la fecha, se debe auditar el entorno fuera de este rango (rango de 64 bits de marcas de tiempo Unix, MySQL que funciona de facto o almacenamiento de base de datos alternativo para los valores). Para rangos más lejanos ( por debajo de 1000, por encima de 9999 ) es probable que se requieran cantidades considerables de código personalizado.

Para cualquier implementación de fechas arbitrarias tiene sentido:

  • almacenarlos en MySQL en formato no sujeto a limitaciones de la base de datos
  • proceso en PHP usando Date/Timecódigo completamente personalizado y / o funciones de WordPress auditadas para no verse afectadas por los límites de marca de tiempo de Unix

Código de prueba de cama

El siguiente código y el conjunto de años seleccionados a mano se han utilizado para la investigación anterior y la prueba de conclusiones:

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
fuente
+1 Solo queda la pregunta: ¿Qué es r()?
kaiser
1
@kaiser php-ref , reemplace con la función de volcado de su elección :)
Rarst