El formato completo ISO 8601 pueden' se puede hacer con una coincidencia de patrón único. Hay demasiada variación.
Algunos ejemplos: from the wikipedia page
- hay un formato "comprimido" que hace números no separadas:
YYYYMMDD
vs YYYY-MM-DD
- El día puede ser omitido:
YYYY-MM-DD
y YYYY-MM
son ambas fechas válidas
- La fecha ordinal también es válida:
YYYY-DDD
, donde DDD
es el día del año (1-365/6)
- Al representar la t ime, los minutos y los segundos se pueden omitir recayendo:
hh:mm:ss
, hh:mm
y hh
son todo momento válidos
- Por otra parte, el tiempo también tiene una versión comprimida:
hhmmss
, hhmm
- Y encima de eso, el tiempo acepta fracciones, utilizando tanto el punto o la coma para indicar fracciones del elemento de tiempo más bajo en la sección de tiempo.
14:30,5
, 1430,5
, 14:30.5
, o 1430.5
, todos representan 14 horas, 30 segundos y medio.
- Finalmente, la sección de zona horaria es opcional. Cuando está presente, puede ser la letra Z,
±hh:mm
, ±hh
o ±hhmm
.
Por lo tanto, hay muchas excepciones posibles a tener en cuenta, si va a analizar de acuerdo con la especificación completa. En ese caso, su código inicial podría tener este aspecto:
function parseDateTime(str)
local Y,M,D = parseDate(str)
local h,m,s = parseTime(str)
local oh,om = parseOffset(str)
return os.time({year=Y, month=M, day=D, hour=(h+oh), min=(m+om), sec=s})
end
Y entonces tendría que crear parseDate
, parseTime
y parseOffset
. El último debería devolver las compensaciones de tiempo desde UTC, mientras que las dos primeras tendrían que tener en cuenta cosas como formatos comprimidos, fracciones de tiempo, separadores de coma o de punto, y cosas por el estilo.
parseDate
probablemente usará el carácter "^"
al comienzo de sus coincidencias de patrón, ya que la fecha debe estar al principio de la cadena.Los patrones de parseTime
probablemente comiencen con "T"
. Y parseOffset
terminará con "$"
, ya que las compensaciones de tiempo, cuando existen, están al final.
A "llena ISO" parseOffset
función podría ser similar a esto:
function parseOffset(str)
if str:sub(-1)=="Z" then return 0,0 end -- ends with Z, Zulu time
-- matches ±hh:mm, ±hhmm or ±hh; else returns nils
local sign, oh, om = str:match("([-+])(%d%d):?(%d?%d?)$")
sign, oh, om = sign or "+", oh or "00", om or "00"
return tonumber(sign .. oh), tonumber(sign .. om)
end
Por cierto, estoy suponiendo que el sistema está funcionando en el tiempo UTC. Si ese no es el caso, tendrá que incluir un desplazamiento adicional en sus horas/minutos para dar cuenta de eso.
function parseDateTime(str)
local Y,M,D = parseDate(str)
local h,m,s = parseTime(str)
local oh,om = parseOffset(str)
local loh,lom = getLocalUTCOffset()
return os.time({year=Y, month=M, day=D, hour=(h+oh-loh), min=(m+om-lom), sec=s})
end
Para obtener compensar sus locales es posible que desee mirar a http://lua-users.org/wiki/TimeZone.
Espero que esto ayude. ¡Saludos!
La respuesta de BTW kikito es buena; solo una nota: podría ser un buen movimiento aceptar '' (espacio) y 'T' para separar la fecha/hora, porque muchas personas y herramientas escriben fechas de estilo ISO de esa manera (tal vez más que usa 'T'!). – snogglethorpe
Gracias por ese puntero. En mi caso, no necesito preocuparme demasiado porque el patrón es conocido: 2011-10-25T00: 29: 55.503-04: 00 –