El problema es que '2/3/2012' es ambiguo. Es d/m/Y? O m/d/Y? En el segundo caso, 31 como primer argumento no tendría sentido, porque sólo hay 12 meses. Es por esto que te da la fecha inicial Unix. Ambiguedades similares ocurrirían si usásemos 2 dígitos para el año en lugar de 4.
Ésta deficiencia es mencionada en la [URL="http://php.net/manual/es/function.strtotime.php"]entrada de strtotime en el manual oficial[/URL].
Para esto existe la muy útil e inusualmente inutilizada [URL="http://www.php.net/manual/es/class.datetime.php"]clase DateTime[/URL], la navaja suiza de la fecha en PHP >= 5.3.0. Con sus métodos
createFromFormat y
Format podemos especificar y mostrar una fecha, respectivamente.
Código PHP:
Ver original<?php
// Nuestro parseador, utilizando la funcion strtotime
function parseFecha_strtotime($fecha)
{
}
// Nuestro parseador, utilizando el objeto DateTime
function parseFecha_DateTime($fecha)
{
return DateTime::createFromFormat('d/m/Y', $fecha)->format('Ymd');
}
// Juego de valores usando barra
$test1 = array('2/3/12', '2/03/12', '02/3/12', '02/03/12', '2/3/2012', '2/03/2012', '02/3/2012', '02/03/2012', '31/03/2012');
// Juego de valores usando guion
$test2 = array('2-3-12', '2-03-12', '02-3-12', '02-03-12', '2-3-2012', '2-03-2012', '02-3-2012', '02-03-2012', '31-03-2012');
// Unir ambos juegos
// Probar con nuestro parseador strtotime
foreach ($fechas as $fecha)
echo parseFecha_strtotime($fecha) . ' (' . $fecha . ')<br />';
echo 'Ahora con DateTime! <br />';
// Probar con nuestro parseador DateTime
foreach ($fechas as $fecha)
echo parseFecha_DateTime($fecha) . ' (' . $fecha . ') <br />';
?>
La salida producida será:
Código HTML:
Ver original20120203 (2/3/12)
20120203 (2/03/12)
20120203 (02/3/12)
20120203 (02/03/12)
20120203 (2/3/2012)
20120203 (2/03/2012)
20120203 (02/3/2012)
20120203 (02/03/2012)
19691231 (31/03/2012)
20020312 (2-3-12)
20020312 (2-03-12)
20020312 (02-3-12)
20020312 (02-03-12)
20120302 (2-3-2012)
20120302 (2-03-2012)
20120302 (02-3-2012)
20120302 (02-03-2012)
20120331 (31-03-2012)
Ahora con DateTime!
00120302 (2/3/12)
00120302 (2/03/12)
00120302 (02/3/12)
00120302 (02/03/12)
20120302 (2/3/2012)
20120302 (2/03/2012)
20120302 (02/3/2012)
20120302 (02/03/2012)
20120331 (31/03/2012)
Fatal error: Call to a member function format() on a non-object in /var/www/fecha.php on line 9
Podemos apreciar que el parseador
strtotime funciona para todos los casos, excepto en '31/03/2012'. Esto está explicado en la entrada del manual de strtotime, se debe a que la barra implica formato americano y 31 no es un mes válido. Sin embargo '31-03-2012' es correctamente convertido tomando 31 como día.
En el parseador
DateTime, como en los argumentos pusimos Y en lugar de y, espera 4 dígitos de año y al recibir sólo 2 convierte el año a 0012. Como nuestro formato contempla barras y no guiones, muere al intentar procesar el segundo juego de fechas. Claramente no es para nada indulgente, y si quisiésemos arreglar estas fallas deberíamos hacer un poco más inteligente a nuestra función.
Recapitulando:
Código PHP:
Ver original<?php
// Para pasar de formato en paradigma OO
$fecha = DateTime::createFromFormat('d/m/Y', '2/3/2012');
echo $fecha->format('Ymd') . '<br />';
// Para pasar en forma procedural
$fecha = date_create_from_format('d/m/Y', '2/3/2012');
?>
Su salida:
Ambos paradigmas producen la misma salida, y se pueden encadenar los 2 métodos en el paradigma OO como en el primer ejemplo, o primero asignarlo a una variable y luego mostrar con formato esa variable. Difieren en el tratamiento de errores, pero me imagino que las excepciones se escapan de tu conocimiento.