Tengo esta marca de fecha:

"2021-06-08T13:09:00.9796129Z"

Y no puedo convertirlo en un objeto DateTime usando CreatefromFormat. Estoy usando un Normalizador de Janefp, por lo que preferiría intentarlo y resolver esto estrictamente usando CreatefromFormat. He probado lo siguiente:

$options = [
    \DateTimeInterface::ATOM,
    \DateTimeInterface::COOKIE,
    \DateTimeInterface::ISO8601,
    \DateTimeInterface::RFC822,
    \DateTimeInterface::RFC850,
    \DateTimeInterface::RFC1036,
    \DateTimeInterface::RFC1123,
    \DateTimeInterface::RFC7231,
    \DateTimeInterface::RFC2822,
    \DateTimeInterface::RFC3339,
    \DateTimeInterface::RFC3339_EXTENDED,
    \DateTimeInterface::RSS,
    \DateTimeInterface::W3C,
    'Y-m-dTH:i:s.uP',
    'Y-m-dTH:i:s.P',
    'Y-m-dTH:i:s.vP',
];

foreach ($options as $name) {
    var_dump(\DateTime::createFromFormat($name, "2021-06-08T13:09:00.9796129Z"));
}

Todo resulta en:

bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)

¿Cuál es el formato correcto?

php
1
mikelovelyuk 8 jun. 2021 a las 16:35

2 respuestas

La mejor respuesta

Tienes un problema simple y un problema más complejo.

El problema simple es que para igualar un T literal, debe escaparlo con una barra invertida. Eso debería permitir este patrón:

'Y-m-d \ th: i: s.up'

(Año Mes-Día, Literal T, Hora: Minuto: Second.Microsegundo, Zona horaria)

El problema complejo es que su marca de tiempo tiene 7 lugares decimales en los segundos, dando una resolución de una décima de un microsegundo . Es por eso que el especificador u no corresponde:

U: microsegundos (hasta seis dígitos)

¿Una solución sería usar el? Especificador que coincide con cualquier byte único:

'Y-m-d \ th: i: s.u? P'

(Año Mes-Día, Literal T, Hora: Minuto: Second.Microsecond, ignora un byte para el dígito adicional, la zona horaria)

var_dump(\DateTime::createFromFormat('Y-m-d\TH:i:s.u?P', "2021-06-08T13:09:00.9796129Z"));

# object(DateTime)#1 (3) {
#   ["date"]=>
#   string(26) "2021-06-08 13:09:00.979612"
#   ["timezone_type"]=>
#   int(2)
#   ["timezone"]=>
#   string(1) "Z"
# }
1
IMSoP 8 jun. 2021 a las 14:02

No estás escapando de la T, por lo que está intentando usar eso como un marcador de posición (abreviatura de TimeZone). El formato correcto sería

'Y-m-d\TH:i:s.u\Z'
0
aynber 8 jun. 2021 a las 13:44