Полный формат ISO 8601 не может быть сделан с одним совпадением шаблона. Слишком много вариаций.
Некоторые примеры со страницы википедии :
- Существует «сжатый» формат, который не разделяет числа:
YYYYMMDD
против YYYY-MM-DD
- День можно опустить:
YYYY-MM-DD
и YYYY-MM
являются действительными датами
- Порядковая дата также действительна:
YYYY-DDD
, где DDD
- день года (1-365 / 6)
- При представлении времени минуты и секунды могут быть опущены:
hh:mm:ss
, hh:mm
и hh
- все действительные времена
- Кроме того, время также имеет сжатую версию:
hhmmss
, hhmm
- Кроме того, время принимает дроби, , используя как точку, так и запятую для обозначения дробей младшего элемента времени в отрезке времени .
14:30,5
, 1430,5
, 14:30.5
или 1430.5
представляют собой 14 часов 30 с половиной.
- Наконец, раздел о часовом поясе является необязательным. При наличии это может быть буква Z,
±hh:mm
, ±hh
или ±hhmm
.
Итак, существует множество возможных исключений, которые следует учитывать, если вы собираетесь анализировать в соответствии с полной спецификацией. В этом случае ваш исходный код может выглядеть так:
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
И тогда вам придется создать parseDate
, parseTime
и parseOffset
. Последний должен возвращать смещения времени из UTC, в то время как первые два должны учитывать такие вещи, как сжатые форматы, доли времени, разделители запятых или точек и т. П.
parseDate
, скорее всего, будет использовать символ "^"
в начале совпадений с образцом, поскольку дата должна быть в начале строки. Шаблоны parseTime
, скорее всего, начнутся с "T"
. И parseOffset
будет заканчиваться "$"
, поскольку смещения времени, когда они существуют, заканчиваются.
Функция "full ISO" parseOffset
может выглядеть примерно так:
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
Кстати, я предполагаю, что ваш компьютер работает в UTC. Если это не так, вам придется включить дополнительное смещение в ваши часы / минуты, чтобы учесть это.
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
Чтобы получить локальное смещение, вы можете посмотреть на http://lua -users.org / wiki / TimeZone .
Надеюсь, это поможет. Привет!