Давайте сразу определимся. В Lua нет понятия «Календарная дата». Есть понятие «время», которое включает в себя как цифру в календаре, так и показания стрелок будильника. Поэтому в дальнейшем будем оперировать термином «время», подразумевая, что оно включает в себя и день/месяц/год и все остальное.
Для хранения времени в Lua 5.1 используются 2 типа данных.
Первый – это таблица с полями
- year (год, четыре цифры)
- month (месяц, 1 – 12)
- day (день, 1 – 31)
- hour (час, 0 – 23)
- min (минуты, 0 – 59)
- sec (секунды, 0 – 61)
- wday (день недели, воскресенью соответствует 1)
- yday (день года)
- isdst (флаг дневного времени суток, тип boolean).
Давайте в дальнейшем такую таблицу именовать как таблицу datetime. Эта таблица может использоваться как в качестве параметра для функций даты/времени языка lua, так и в качестве возвращаемого результата. В зависимости от контекста не все поля требуют заполнения.
Второй формат хранения даты и времени – это так называемый Posix формат времени (или Unix-время).
Представление времени в виде количества секунд удобно использовать для сравнения и хранения дат (дата и время в этом формате занимают всего 4 или 8 байтов). При необходимости обращения к элементам дат (день, месяц, год) секунды можно преобразовать в любой подходящий формат (и наоборот), но если такие преобразования выполняются часто, они снижают производительность.
Я отдельно подчеркну удобство posix формата времени. Мы можем легко прибавлять, вычитать, сравнивать и находить разницу между двумя временными моментами путем простейших арифметических операций.
Теперь о функциях работы со временем, которые нам предоставляет Lua 5.1. Собственно, основных две:
- os.time ([table]) – преобразует таблицу datetime в posix
- os.date ([format [, time]]) – преобразует posix в таблицу datetime.
Как видно, они комплементарные. Однако на самом деле все намного интереснее. Давайте остановимся на каждой из них подробнее. В примерах ниже я буду использовать функцию print(). Если у Вас не установлен пакет Lua 5.1, а только терминал QUIK, замените print() на message()
Преобразование таблицы DATETIME в POSIX:
datetime = { year = 2013, month = 09, day = 13, hour = 21, min = 40, sec = 15}
seconds_since_epoch = os.time(datetime) print(tostring(seconds_since_epoch))
Преобразование POSIX в таблицу DATETIME:
seconds_since_epoch = 1379094015
datetime = os.date("!*t",seconds_since_epoch)
print( "year = " .. tostring(datetime.year) .. " " ..
" month = " .. tostring(datetime.month) .. " " ..
"day = " .. tostring(datetime.day) .. " " ..
"hour = " .. tostring(datetime.hour) .. " " ..
"min = " .. tostring(datetime.min) .. " " ..
"sec = " .. tostring(datetime.sec) .. " " ..
"weekday = " .. tostring(datetime.wday) .. " " ..
"day of year = " .. tostring(datetime.yday) .. " " ..
" iddst = " .. tostring(datetime.isdst))
Первым параметром os.date() идет строка «!*t». Расшифрую. Если первый параметр начинается с ‘!’, то время форматируется в соответствии с универсальным глобальным временем (по Гринвичу). Далее если следуют символы «*t», то os.date() возвращает таблицу datetime.
Получение текущего времени в формате POSIX:
Получение текущего времени в формате DATETIME:
datetime = os.date("!*t",os.time())
print( tostring(datetime.year) .. " " ..
tostring(datetime.month) .. " " ..
tostring(datetime.day) .. " " ..
tostring(datetime.hour) .. " " ..
tostring(datetime.min) .. " " ..
tostring(datetime.sec) .. " " ..
tostring(datetime.wday) .. " " ..
tostring(datetime.yday) .. " " ..<
tostring(datetime.isdst))
Варианты работы функции OS.DATE():
Собственно, про os.time() сказать больше нечего. А вот у второй функции еще масса возможностей.
Первый параметр функции os.date(), как мы видели выше, должен быть текстовой строкой, которая управляет поведением функции и возвращаемым значением. Вот полный список возможных строк и, соответственно, возвращаемых функцией значений:
%a |
abbreviated weekday name (e.g., Wed) |
%A |
full weekday name (e.g., Wednesday) |
%b |
abbreviated month name (e.g., Sep) |
%B |
full month name (e.g., September) |
%c |
date and time (e.g., 09/16/98 23:48:10) |
%d |
day of the month (16) [01-31] |
%H |
hour, using a 24-hour clock (23) [00-23] |
%I |
hour, using a 12-hour clock (11) [01-12] |
%M |
minute (48) [00-59] |
%m |
month (09) [01-12] |
%p |
either «am» or «pm» (pm) |
%S |
second (10) [00-61] |
%U |
sunday week of the year 00 (53) |
%w |
weekday (3) [0-6 = Sunday-Saturday] |
%W |
monday week of the year, from 00 (48) |
%x |
date (e.g., 09/16/98) |
%X |
time (e.g., 23:48:10) |
%Y |
full year (1998) |
%y |
two-digit year (98) [00-99] |
%z |
timezone string |
%% |
the character % |
Преобразование строки даты в DATETIME:
В терминале Quik строковое представление даты бывает в двух форматах. Любой из них легко преобразуется в формат datetime.
Для формата DD.MM.YYYY:
datetime = {}
datetime.day,datetine.month,datetime.year = string.match("13.09.2013","(%d*)\.(%d*)\.(%d*)")
Для формата YYYYMMDD:
datetime = {}
datetime.year,datetime.month,datetime.day = string.match("20130913","(%d%d%d%d)(%d%d)(%d%d)")
Замечу, что в обоих случаях string.match() выдает текстовые строки, а не числовые значения, которые сохраняются в datetime. Тем не менее os.time() прекрасно это понимает.
Преобразование строки времени в DATETIME:
datetime={}
datetime.hour,datetime.min,datetime.sec = string.match("21:17:43","(%d%d)%p(%d%d)%p(%d%d)")
Замечу, что поля year, month и day должны быть также заполнены.