Этот модуль предоставляет функции даты для использования другими модулями. Поддерживаются даты в григорианском и юлианском календарях с 9999 г. до н.э. до 9999 г. н.э. Календари являются пролептическими - предполагается, что они применяются в любое время без каких-либо отклонений.
Дата с необязательным временем может быть указана в различных форматах и может быть преобразована для отображения с использованием различных форматов, например 1 апреля 2016 г. или 1 апреля 2016 г. Свойства даты включают дату по юлианскому календарю. и его серийная дата по григорианскому календарю, а также день недели и день года.
Даты можно сравнивать (например, date1 <= date2
) и использовать с добавлением или вычитанием (например, date + '3 months'
). Разницу между двумя датами можно определить с помощью date1 - date2
. Эти операции работают с датами как по григорианскому, так и по юлианскому календарю, но date1 - date2
равны нулю, если две даты используют разные календари.
Модуль предоставляет следующие элементы.
Экспорт | Описание |
---|---|
_current | Таблица с текущим годом, месяцем, днем, часом, минутой, секундой. |
_Date | Функция, возвращающая таблицу на указанную дату. |
_days_in_month | Функция, возвращающая количество дней в месяце. |
Ниже приведены примеры использования модуля:
- Модуль: Дата / пример • Демонстрация, показывающая, как можно использовать Модуль: Дата.
- Обсуждение модуля: Дата / пример • Результат демонстрации.
Форматированный вывод
Дата может быть отформатирована как текст.
local Date = require ( 'Модуль: Дата' ). _Date local text = Date ( 2016 , 7 , 1 ): text () - результат: '1 июля 2016' local text = Date ( 2016 , 7 , 1 ): text ( '% -d% B' ) - результат это '1 июля' local text = Date ( '1 июля 2016' ): text ( 'mdy' ) - результат "1 июля 2016 г."
Доступны следующие упрощенные коды форматирования.
Код | Результат |
---|---|
хм | час: минута, с "утра" или "после полудня" или вариант, если указан (14:30 или 14:30 или вариант) |
хм | час: минута: секунда (14:30:45) |
ymd | год-месяц-день (2016-07-01) |
MDY | месяц число, год (1 июля 2016 г.) |
dmy | день месяц год (1 июля 2016 г.) |
Доступны следующие коды форматирования (аналогичные strftime ).
Код | Результат |
---|---|
% a | Аббревиатура дня: Пн, Вт, ... |
% А | Название дня: понедельник, вторник, ... |
% u | День недели: с 1 по 7 (с понедельника по воскресенье) |
% w | День недели: от 0 до 6 (с воскресенья по субботу) |
% d | День месяца с нулями: с 01 по 31 |
% b | Аббревиатура месяца: с января по декабрь |
% B | Название месяца: с января по декабрь |
% m | Месяц с нулями: с 01 по 12 |
% Y | Год дополнен нулями: 0012, 0120, 1200 |
%ЧАС | Часовые 24-часовые часы с нулями: с 00 до 23 |
%Я | Часы в 12-часовом формате с нулями: с 01 по 12 |
%п | AM или PM или как в вариантах |
% M | Минуты с нулями: от 00 до 59 |
% S | Второе дополнение с нулями: от 00 до 59 |
% j | День года с нулями: с 001 по 366 |
% -d | День месяца: с 1 по 31 |
% -м | Месяц: с 1 по 12 |
% -Y | Год: 12, 120, 1200 |
%-ЧАС | Часы: с 0 до 23 |
% -M | Минуты: от 0 до 59 |
% -S | Второй: от 0 до 59 |
% -j | День года: с 1 по 366 |
%-Я | Час: с 1 до 12 |
%% | % |
Кроме того, можно использовать (где любое свойство даты).%{property}
property
Например, Date('1 Feb 2015 14:30:45 A.D.')
имеет следующие свойства.
Код | Результат |
---|---|
%{календарь} | Григорианский |
%{год} | 2015 г. |
%{месяц} | 2 |
%{день} | 1 |
%{час} | 14 |
% {минута} | 30 |
%{второй} | 45 |
% {dayabbr} | солнце |
% {dayname} | воскресенье |
%{день недели} | 0 |
% {dow} | 0 (так же, как dayofweek) |
% {dayofweekiso} | 7 |
% {dowiso} | 7 (так же, как dayofweekiso) |
% {dayofyear} | 32 |
% {era} | ОБЪЯВЛЕНИЕ |
% {gsd} | 735630 (количество дней с 1 января 1 года н.э., первый день 1) |
% {juliandate} | 2457055.1046875 ( юлианский день ) |
% {jd} | 2457055.1046875 (то же, что и juliandate) |
% {isleapyear} | ложный |
% {monthdays} | 28 год |
% {monthabbr} | Фев |
% {monthname} | Февраль |
Доступны некоторые ярлыки. Учитывая date = Date('1 Feb 2015 14:30')
, были бы достигнуты следующие результаты.
Код | Описание | Пример результата | Эквивалентный формат |
---|---|---|---|
дата: текст ('% c') | Дата и время | 14:30, 1 февраля 2015 г. | % -I:% M% p% -d% B% -Y% {era} |
дата: текст ('% x') | Дата | 1 февраля 2015 г. | % -d% B% -Y% {era} |
дата: текст ('% X') | время | 14:30 | % -I:% M% p |
Юлианская дата
Ниже приведен пример преобразования даты по юлианскому календарю в дату с последующим получением информации о дате.
- Код - Дата результата = требуется ( 'Модуль: Дата' ). _Date date = Дата ( 'juliandate' , 320 ) число = дата . GSD - -1721105 номер = дата . jd - 320 текст = дата . dayname - суббота text = date : text () - 9 октября 4713 г. & nbsp; BC text = date : text( '% Y-% m-% d' ) - 4713-10-09 text = date : text ( '% {era}% Y-% m-% d' ) - BC 4713-10-09 text = date : text ( '% Y-% m-% d% {era}' ) - 4713-10-09 & nbsp; BC text = date : text ( '% Y-% m-% d% {era}' , ' era = BCE ' ) - 4713-10-09 & nbsp; BCE text = date : text ( '% Y-% m-% d ' , ' era = BCNEGATIVE ') - -4712-10-09 текст = date : text ( '% Y-% m-% d' , 'era = BCMINUS' ) - −4712-10-09 (используется МИНУСНЫЙ ЗНАК Юникода U + 2212) text = Date ( 'juliandate' , 320 ): text ( '% {gsd}% {jd}' ) - -1721105 320 text = Дата ( '9 октября 4713 г. до н.э.' ): text ( '% {gsd}% {jd}' ) - -1721105 320 text = Дата ( - 4712 , 10 , 9 ): текст ('% {gsd}% {jd}' ) - -1721105 320
Различия в датах
Разницу между двумя датами можно определить с помощью date1 - date2
. Результат действителен, если обе даты используют григорианский календарь или если обе даты используют юлианский календарь, в противном случае результат равен нулю. Возраст и продолжительность могут быть рассчитаны по разнице дат.
Например:
- Код - Дата результата = требуется ( 'Модуль: Дата' ). _DATE date1 = Дата ( '21 марта 2015' ) date2 = Дата ( '4 декабря 1999' ) дифф = date1 - date2 d = дифф . age_days - 5586 г , м , д = разн . лет , разн . месяцев , разн . дней - 15, 3, 17 (15 лет + 3 месяца + 17 дней) y , m , d = diff : age ( 'ymd' ) - 15, 3, 17 y , m , w , d = diff : age ( 'ymwd' ) - 15, 3, 2, 3 (15 лет + 3 месяца + 2 недели + 3 дня) y , m , w , d = diff : duration ( 'ymwd' ) - 15, 3, 2, 4 d = разница : продолжительность( 'd' ) - 5587 (продолжительность включает последний день)
Разница в датах содержит исходные даты, за исключением того, что они меняются местами diff.date1 >= diff.date2
( diff.date1
это более поздняя дата). Это показано ниже.
date1 = Дата ( '21 марта 2015' ) date2 = Дата ( '4 Декабрь 1999' ) дифф = date1 - date2 отр = дифф . isnegative - ложный текст = diff . date1 : text () - 21 марта 2015 г. text = diff . date2 : текст () - 4 декабря 1999 дифф = date2 - date1 отр = дифф .isnegative - true (даты поменялись местами) text = diff . date1 : text () - 21 марта 2015 г. text = diff . date2 : text () - 4 декабря 1999 г.
Разница в датах также имеет разницу во времени:
date1 = Дата ( '8 марта 2016 0:30:45' ) дата2 = Дата ( '19 января 2014 22:55' ) Diff = date1 - дата2 у , м , д = разн . лет , разн . месяцев , разн . дней - 2, 1, 17 Н , М , S = разн . часов , разн . минут , разн . секунды - 1, 35, 45
Разница в датах может быть добавлена к дате или вычтена из даты.
date1 = Дата ( '8 марта 2016 0:30:45' ) date2 = Дата ( '19 января 2014 22:55' ) дифф = date1 - date2 date3 = date2 + дифференциал date4 = date1 - дифф текст = date3 : текст ( ' ymd hms ' ) - 2016-03-08 00:30:45 text = date4 : text ( ' ymd hms ' ) - 2014-01-19 22:55:00 equal = ( date1 == date3 ) - истинные равные = ( дата2 == date4 ) - истинно
Методы возраста и продолжительности разницы в датах принимают код, который определяет компоненты, которые должны быть возвращены. Дополнительный день включен в метод продолжительности, потому что он включает последний день.
Код | Возвращенные значения |
---|---|
'ymwd' | годы, месяцы, недели, дни |
'ymd' | годы, месяцы, дни |
'ym' | лет, месяцев |
'y' | годы |
'm' | месяцы |
'wd' | недели, дни |
'w' | недели |
'd' | дней |
- Функции даты для использования другими модулями.- I18N и часовые пояса не поддерживаются.local MINUS = '-' - Unicode U + 2212 МИНУСНЫЙ ЗНАКлокальный этаж = math.floorlocal Date , DateDiff , diffmt - форвардные объявленияlocal uniq = { 'уникальный идентификатор' }локальная функция is_date ( t )- Система, используемая для создания даты только для чтения, означает, что нет уникальных- метатаблица, удобная для проверки. тип возврата ( t ) == 'table' и t . _id == uniqконецлокальная функция is_diff ( t ) тип возврата ( t ) == 'table' и getmetatable ( t ) == diffmtконецлокальная функция _list_join ( список , sep )вернуть table.concat ( список , sep )конецлокальная коллекция функций ()- Верните стол для хранения предметов.return {п = 0 ,добавить = функция ( сам , элемент )я . n = себя . п + 1сам [ сам . n ] = элементконец ,join = _list_join ,}конецлокальная функция strip_to_nil ( текст )- Если текст является строкой, вернуть его обрезанное содержимое или ноль, если он пуст.- В противном случае вернуть текст (удобно, когда поля даты предоставляются из- другой модуль, который может передавать строку, число или другой тип).если type ( text ) == 'string', тотекст = текст : совпадение ( '(% S .-)% s * $' )конец текст возвратаконецлокальная функция is_leap_year ( год , имя )- Вернуть true, если год високосный.если calname == 'Julian', тогдавозвращение год % 4 == 0конецдоходность ( год % 4 == 0 и год % 100 ~ = 0 ) или год % 400 == 0конецлокальная функция days_in_month ( год , месяц , calname )- Возвращает количество дней (1..31) в данном месяце (1..12).если month == 2 и is_leap_year ( год , имя ), товозврат 29конецreturn ({ 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 }) [ месяц ]конецлокальная функция h_m_s ( время )- Возврат часов, минут, секунд, извлеченных из доли дня.время = этаж ( время * 24 * 3600 + 0,5 ) - количество секундместная секунда = время % 60время = этаж ( время / 60 )возвратный этаж ( время / 60 ), время % 60 , секундаконецлокальная функция hms ( дата )- Возвращает долю дня от даты, где (0 <= дробь <1)- если значения действительны, но могут быть любыми, если они находятся вне диапазона.возврат ( дата . час + ( дата . минута + дата . секунда / 60 ) / 60 ) / 24конецлокальная функция julian_date ( дата )- Возврат jd, jdz из даты по юлианскому или григорианскому календарю, где- jd = дата по юлианскому календарю и ее дробная часть равна нулю в полдень- jdz = то же самое, но предположим, что время 00:00:00, если время не указано- http://www.tondering.dk/claus/cal/julperiod.php#formula- Тестирование показывает, что это работает для всех дат с -9999 по 9999 год!- JDN 0 - это 24-часовой период, начинающийся в полдень понедельника по всемирному координированному времени.- 1 января 4713 г. до н.э. = (-4712, 1, 1) по юлианскому календарю- 24 ноября 4714 г. до н.э. = (-4713, 11, 24) по григорианскому календарюместное смещениеместный а = этаж (( 14 - числа . мес. ) / 12 )местный y = дата . год + 4800 - аесли дата . calendar == 'Julian', затемoffset = floor ( y / 4 ) - 32083ещесмещение = этаж ( г / 4 ) - этаж ( г / 100 ) + этаж ( г / 400 ) - 32045конецместный м = дата . месяц + 12 * а - 3местный jd = дата . день + пол (( 153 * м + 2 ) / 5 ) + 365 * y + смещениеесли дата . время тогдаJD = JD + HMS ( дата ) - 0,5вернуть jd , jdконецвозврат jd , jd - 0,5конецлокальная функция set_date_from_jd ( дата )- Установите поля даты таблицы из ее поля даты по юлианскому календарю.- Вернуть истину, если дата действительна.- http://www.tondering.dk/claus/cal/julperiod.php#formula- Это обрабатывает пролептические юлианский и григорианский календари.- Отрицательные юлианские даты не определены, но работают.местное имя = дата . календарьлокальный минимум , максимум - минимальные / максимальные пределы для диапазонов дат от -9999-01-01 до 9999-12-31если calname == 'Gregorian', тогданизкий , высокий = - 1930999,5 , 5373484,49999elseif calname == 'Julian' тогданизкий , высокий = - 1931076,5 , 5373557,49999ещевозвращатьсяконецместный jd = дата . jdесли нет ( type ( jd ) == 'number' и low <= jd и jd <= high ), товозвращатьсяконецместный jdn = этаж ( jd )если дата . время тогдаместное время = юлианский день - JDN - 0 <= время <1если время > = 0,5, то - если в полночь следующего дня или позжеjdn = jdn + 1время = время - 0,5ещевремя = время + 0,5конецдата . час , дата . минута , дата . second = h_m_s ( время )ещедата . второй = 0дата . минута = 0дата . час = 0конецместный б , весли calname == 'Julian', тогдаб = 0с = jdn + 32082иначе - григорианскийместный a = jdn + 32044b = этаж (( 4 * a + 3 ) / 146097 )c = a - этаж ( 146097 * b / 4 )конецместный d = этаж (( 4 * c + 3 ) / 1461 )местный e = c - этаж ( 1461 * d / 4 )местный m = этаж (( 5 * e + 2 ) / 153 )дата . день = e - этаж (( 153 * m + 2 ) / 5 ) + 1дата . месяц = м + 3 - 12 * пол ( м / 10 )дата . год = 100 * b + d - 4800 + этаж ( м / 10 )вернуть истинуконецлокальная функция fix_numbers ( числа , y , m , d , H , M , S , partial , hastime , calendar )- Поместите результат нормализации заданных значений в номера таблиц.- Результат будет иметь допустимые значения m, d, если y действительно; звонящий проверяет y.- Соблюдается логика PHP mktime, где m или d могут быть равны нулю, чтобы означать- предыдущий блок, -1 - предыдущий и т. д.- Положительные значения переносятся.местная датаесли нет ( 1 <= m и m <= 12 ), тоdate = Дата ( y , 1 , 1 )если не дата, то верните конецдата = дата + (( m - 1 ) .. 'm' )y , m = дата . год , дата . месяцконецместные days_hmsесли не частичный, тоесли hastime и Н и М и S , тоесли нет ( 0 <= H и H <= 23 и0 <= M и M <= 59 и0 <= S и S <= 59 ), тогдаdays_hms = hms ({ час = Ч , минута = М , секунда = С })конецконецесли days_hms или нет ( 1 <= d и d <= days_in_month ( y , m , calendar )), тоdate = date или Date ( y , m , 1 )если не дата, то верните конецdate = date + ( d - 1 + ( days_hms или 0 ))y , m , d = дата . год , дата . месяц , число . деньесли days_hms, тоH , M , S = дата . час , дата . минута , дата . второйконецконецконецчисла . год = yчисла . месяц = мчисла . день = десли days_hms, то- Не устанавливайте H, если он не был действительным, потому что действительный H установит время.числа . час = Hчисла . минута = Mчисла . второй = Sконецконецлокальная функция set_date_from_numbers ( дата , числа , параметры )- Установить поля таблицы даты из числовых значений.- Вернуть истину, если дата действительна.если type ( числа ) ~ = 'table', товозвращатьсяконецместный y = числа . год или дату . годместный m = числа . месяц или число . месяцместный d = числа . день или дату . деньместный H = числа . часместный M = числа . минута или дата . минута или 0местный S = числа . второй или свидание . второй или 0местное need_fixесли y и m и d, тодата . частичный = нольесли нет ( - 9999 <= y и y <= 9999 и1 <= m и m <= 12 и1 <= д и д <= Days_in_Month ( у , м , дата . Календарь )) , тоесли не дата . want_fix тогдавозвращатьсяконецneed_fix = trueконециначе, если y и дата . частичный тогдаесли d или нет ( - 9999 <= y и y <= 9999 ), товозвращатьсяконецесли m, а не ( 1 <= m и m <= 12 ), тоесли не дата . want_fix тогдавозвращатьсяконецneed_fix = trueконецещевозвращатьсяконецесли дата . частичный тогдаH = nil - игнорировать в любое времяM = нольS = нольещеесли H, то- Невозможно установить M или S, не установив также H.дата . hastime = trueещеH = 0конецесли нет ( 0 <= H и H <= 23 и0 <= M и M <= 59 и0 <= S и S <= 59 ), тогдаесли дата . want_fix тогдаneed_fix = trueещевозвращатьсяконецконецконецдата . want_fix = нольесли need_fix тоfix_numbers ( числа , y , m , d , H , M , S , дата . частичное , дата . hastime , дата . календарь )вернуть set_date_from_numbers ( дата , числа , параметры )конецдата . год = y - от -9999 до 9999 ('n BC' → год = 1 - n)дата . month = m - от 1 до 12 (может быть нулевым, если частично)дата . день = d - от 1 до 31 (* = ноль, если частично)дата . час = H - от 0 до 59 (*)дата . минута = M - от 0 до 59 (*)дата . второй = S - от 0 до 59 (*)если type ( options ) == 'table', тодля _ , k в ipairs ({ 'am' , 'era' , 'format' }) сделайтеесли варианты [ k ], тодата . options [ k ] = options [ k ]конецконецконецвернуть истинуконецлокальная функция make_option_table ( options1 , options2 )- Если options1 является строкой, вернуть таблицу с ее настройками, или- если это таблица, используйте ее настройки.- Отсутствующие параметры устанавливаются из таблицы options2 или значений по умолчанию.- Если используется значение по умолчанию, устанавливается флаг, чтобы вызывающий знал, что значение не было установлено намеренно.- Допустимые настройки параметров:- am: "am", "am", "AM", "AM"- «pm», «pm», «PM», «PM» (каждое имеет то же значение, что и соответствующий пункт выше)- эра: BCMINUS, BCNEGATIVE, BC, BC, BCE, BCE, AD, AD, CE, CE.- Вариант am = 'am' не означает, что сейчас AM; это означает, что используется "am" или "pm", в зависимости от часа,- и am = 'pm' имеет то же значение.- Аналогично, era = 'BC' означает, что 'BC' используется, если год <= 0.- BCMINUS отображает МИНУС, если год <0 и формат отображения не включает% {era}.- BCNEGATIVE аналогично, но отображает дефис.локальный результат = {по умолчанию = {} }если type ( options1 ) == 'table', торезультат . am = options1 . являюсьрезультат . era = options1 . эраelseif type ( options1 ) == 'строка', затем- Пример: «am: AM era: BC» или «am = AM era = BC».для элемента в options1 : gmatch ( '% S +' ) dolocal lhs , rhs = item : match ( '^ (% w +) [: =] (. +) $' )если lhs тогдарезультат [ lhs ] = rhsконецконецконецoptions2 = type ( options2 ) == 'table' и options2 или {}местные значения по умолчанию = { am = 'am' , era = 'BC' }для к , v в паре ( по умолчанию ) делаетесли не результат [ k ], тоесли options2 [ k ], торезультат [ k ] = options2 [ k ]ещерезультат [ k ] = vрезультат . по умолчанию [ k ] = истинаконецконецконецвернуть результатконецlocal ampm_options = {- lhs = вводимый текст принимается как опция am / pm- rhs = внутренний код[ 'am' ] = 'am' ,[ 'AM' ] = 'AM' ,[ 'am' ] = 'am' ,[ 'AM' ] = 'AM' ,[ 'pm' ] = 'am' , - то же, что и am[ 'PM' ] = 'AM' ,[ 'pm' ] = 'am' ,[ 'PM' ] = 'AM' ,}local era_text = {- Текст для отображения эпохи с положительным годом (после настройки- заменив год на 1 - год, если date.year <= 0).- options.era = {год <= 0, год> 0}[ 'BCMINUS' ] = { 'BC' , '' , isbc = true , sign = MINUS },[ 'BCNEGATIVE' ] = { 'BC' , '' , isbc = true , sign = '-' },[ 'BC' ] = { 'BC' , '' , isbc = true },[ 'BC' ] = { 'BC' , '' , isbc = true },[ 'BCE' ] = { 'BCE' , '' , isbc = true },[ 'BCE' ] = { 'BCE' , '' , isbc = true },[ 'AD' ] = { 'BC' , 'AD' },[ 'AD' ] = { 'BC' , 'AD' },[ 'CE' ] = { 'BCE' , 'CE' },[ 'CE' ] = { 'BCE' , 'CE' },}локальная функция get_era_for_year ( эра , год )return ( era_text [ era ] или era_text [ 'BC' ]) [ год > 0 и 2 или 1 ] или ""конецлокальная функция strftime ( дата , формат , параметры )- Дата возврата, отформатированная в виде строки с использованием кодов, аналогичных этим- в библиотечной функции C strftime.локальный sformat = string.formatместные ярлыки = {[ '% c' ] = '% -I:% M% p% -d% B% -Y% {era}' , - дата и время: 14:30 1 апреля 2016 г.[ '% x' ] = '% -d% B% -Y% {era}' , - дата: 1 апреля 2016 г.[ '% X' ] = '% -I:% M% p' , - время: 14:30}если ярлыки [ формат ], тоformat = ярлыки [ формат ]конецместные коды = {a = { field = 'dayabbr' },A = { field = 'dayname' },b = { field = 'monthabbr' },B = { field = 'monthname' },u = { fmt = '% d' , field = 'dowiso' },w = { fmt = '% d' , field = 'dow' },d = { fmt = '% 02d' , fmt2 = '% d' , field = 'day' },m = { fmt = '% 02d' , fmt2 = '% d' , field = 'month' },Y = { fmt = '% 04d' , fmt2 = '% d' , field = 'year' },H = { fmt = '% 02d' , fmt2 = '% d' , field = 'hour' },M = { fmt = '% 02d' , fmt2 = '% d' , field = 'minute' },S = { fmt = '% 02d' , fmt2 = '% d' , field = 'second' },j = { fmt = '% 03d' , fmt2 = '% d' , field = 'dayofyear' },I = { fmt = '% 02d' , fmt2 = '% d' , field = 'hour' , special = 'hour12' },p = { field = 'hour' , special = 'am' },}options = make_option_table ( параметры , дата . параметры )локальный amopt = параметры . являюсьlocal eraopt = параметры . эралокальная функция replace_code ( пробелы , модификатор , идентификатор )местный код = коды [ id ]если код, томестный fmt = код . fmtесли модификатор == '-' и код . fmt2 тогдаfmt = код . fmt2конецместное значение = дата [ код . поле ]если не значение, тоreturn nil - неопределенное поле в частичной датеконецместный специальный = код . специальныйесли особенный, тоесли special == 'hour12', тогдазначение = значение % 12значение = значение == 0 и 12 или значениеelseif special == 'am' тогдаlocal ap = ({[ 'am' ] = { 'am' , 'pm' },[ 'AM' ] = { 'AM' , 'PM' },[ 'AM' ] = { 'AM' , 'PM' },}) [ ampm_options [ amopt ]] или { 'am' , 'pm' }return ( пробелы == '' и '' или '& nbsp;' ) .. ( значение < 12 и ap [ 1 ] или ap [ 2 ])конецконецесли код . field == 'year' тогдаместный знак = ( era_text [ eraopt ] или {}). знакесли не знак или формат : find ( '% {era}' , 1 , true ), тознак = ''если значение <= 0, тоvalue = 1 - значениеконецещеесли значение > = 0, тознак = ''ещезначение = - значениеконецконецвернуть пробелы .. знак .. sformat ( fmt , значение )конецвернуть пробелы .. ( fmt и sformat ( fmt , value ) или значение )конецконецлокальная функция replace_property ( пробелы , id )если id == 'era', то- Особый случай, поэтому можно использовать опцию местной эпохи.локальный результат = get_era_for_year ( eraopt , дата . год )если результат == '' товернуться ''конецreturn ( пробелы == '' и '' или '& nbsp;' ) .. результатконецлокальный результат = дата [ id ]если тип ( результат ) == 'строка', товернуть пробелы .. результатконецесли type ( result ) == 'number', товернуть пробелы .. tostring ( результат )конецесли type ( result ) == 'boolean', товернуть пробелы .. ( результат и '1' или '0' )конец- Это происходит, если id является неопределенным полем в частичной дате или является именем функции.вернуть нольконецместный PERCENT = ' \ 127 PERCENT \ 127 'возврат ( формат: gsub ( '%%%%' , PERCENT ): gsub ( '(% s *) %% {(% w +)}' , replace_property ): gsub ( '(% s *) %% (% -?) (% a)' , replace_code ): gsub ( PERCENT , '%%' ))конецлокальная функция _date_text ( дата , fmt , параметры )- Вернуть отформатированную строку, представляющую заданную дату.если не is_date ( дата ), тоerror ( 'date: text: нужна дата (используйте "date: text ()" с двоеточием)' , 2 )конецесли type ( fmt ) == 'string' и fmt : match ( '% S' ), тоесли fmt : find ( '%' , 1 , true ), товернуть strftime ( дата , fmt , параметры )конецelseif дата . частичный тогдаfmt = дата . месяц и "мой" или "у"ещеfmt = 'dmy'если дата . время тогдаfmt = ( date . second > 0 и 'hms' или 'hm' ) .. fmtконецконецлокальная функция bad_format ()- Для согласованности с другими форматами, верните заданный формат.- (или очищенный формат, если оригинал не был строкой), если он недействителен.вернуть мв . текст . Nowiki ( FMT )конецесли дата . частичный тогда- Игнорировать дни в стандартных форматах, например ymd.если fmt == 'ym' или fmt == 'ymd', тогдаfmt = дата . месяц и "% Y-% m% {era}" или "% Y% {era}"elseif fmt == 'my' или fmt == 'dmy' или fmt == 'mdy' тогдаfmt = дата . месяц и "% B% -Y% {era}" или "% -Y% {era}"elseif fmt == 'y' тогдаfmt = дата . месяц и "% -Y% {эра}" или "% -Y% {эра}"ещевернуть bad_format ()конецвернуть strftime ( дата , fmt , параметры )конецлокальная функция hm_fmt ()local plain = make_option_table ( параметры , дата . параметры ). по умолчанию . являюсьвернуть простой и '% H:% M' или '% -I:% M% p'конецlocal need_time = date . времяместный t = collection ()для элемента в fmt : gmatch ( '% S +' ) doместный жесли item == 'hm', тогдаf = hm_fmt ()need_time = falseelseif item == 'hms' тогдаf = '% H:% M:% S'need_time = falseelseif item == 'ymd' тогдаf = '% Y-% m-% d% {era}'elseif item == 'mdy' тогдаf = '% B% -d,% -Y% {era}'elseif item == 'dmy' тогдаf = '% -d% B% -Y% {era}'ещевернуть bad_format ()конецt : добавить ( f )конецfmt = t : присоединиться ( '' )если need_time тогдаfmt = hm_fmt () .. '' .. fmtконецвернуть strftime ( дата , fmt , параметры )конецlocal day_info = {- 0 = вс до 6 = сб[ 0 ] = { 'Sun' , 'Sunday' },{ 'Пн' , 'Понедельник' },{ 'Вт' , 'вторник' },{ 'Среда' , 'среда' },{ 'Thu' , 'Thursday' },{ 'Пт' , 'Пятница' },{ 'Sat' , 'Saturday' },}local month_info = {- 1 = с января по 12 = декабрь{ 'Январь' , 'Январь' },{ 'Feb' , 'February' },{ 'Mar' , 'March' },{ 'Apr' , 'April' },{ 'May' , 'May' },{ 'Июнь' , 'июнь' },{ 'Июль' , 'июль' },{ 'Aug' , 'August' },{ 'Sep' , 'September' },{ 'Oct' , 'October' },{ 'Nov' , 'November' },{ 'Dec' , 'December' },}локальная функция name_to_number ( текст , перевод )если type ( text ) == 'string', тоreturn translate [ текст : lower ()]конецконецлокальная функция номер_дня ( текст )return name_to_number ( текст , {солнце = 0 , воскресенье = 0 ,пн = 1 , понедельник = 1 ,Вт = 2 , вторник = 2 ,ср = 3 , среда = 3 ,чт = 4 , четверг = 4 ,пт = 5 , пятница = 5 ,сб = 6 , суббота = 6 ,})конецлокальная функция month_number ( текст )return name_to_number ( текст , {январь = 1 , январь = 1 ,февраль = 2 , февраль = 2 ,мар = 3 , марш = 3 ,апр = 4 , апрель = 4 ,май = 5 ,июн = 6 , июнь = 6 ,июл = 7 , июль = 7 ,Августе = 8 , август = 8 ,Сентябрь = 9 , сентябрь = 9 , сентябрь = 9 ,Октябрь = 10 , октябрь = 10 ,ноя = 11 , ноябрь = 11 ,декабрь = 12 , декабрь = 12 ,})конецлокальная функция _list_text ( список , fmt )- Вернуть список отформатированных строк из списка дат.если не type ( list ) == 'table', тогдаerror ( 'дата: список: текст: нужен "список: текст ()" с двоеточием' , 2 )конецлокальный результат = { join = _list_join }для i , дата в ipairs ( список ) делатьрезультат [ i ] = дата : текст ( fmt )конецвернуть результатконецлокальная функция _date_list ( дата , спецификация )- Вернуть возможно пустую нумерованную таблицу дат, соответствующих спецификации.- Даты в списке расположены в порядке возрастания (сначала самая старая дата).- Спецификация должна быть строкой вида «<количество> <день> <op>».- где каждый элемент является необязательным и- count = количество требуемых элементов в списке- день = аббревиатура или название, например Понедельник или Понедельник.- op =>,> =, <, <= (по умолчанию> означает после даты)- Если счетчик не указан, список предназначен для указанных дней в дате месяца.- День по умолчанию - это день даты.- В спецификации также может быть положительное или отрицательное число:- -5 эквивалентно '5 <'- 5 эквивалентно «5», что означает «5>».если не is_date ( дата ), тоerror ( 'date: list: нужна дата (используйте "date: list ()" с двоеточием)' , 2 )конецлокальный список = { text = _list_text }если дата . частичный тогда список возвратаконецлокальный счетчик , смещение , операцияlocal ops = {[ '> =' ] = { before = false , include = true },[ '>' ] = { before = false , include = false },[ '<=' ] = { before = true , include = true },[ '<' ] = { before = true , include = false },}если спецификация, тоесли type ( spec ) == 'number', тоcount = floor ( spec + 0,5 )если count < 0, токол = - подсчетоперация = ops [ '<' ]конецelseif type ( spec ) == 'строка', затемместное число , день , op = spec : match ( '^% s * (% d *)% s * (% a *)% s * ([<> =] *)% s * $' )если не число, то список возвратаконецесли num ~ = '' токол = ToNumber ( Num )конецесли день ~ = '' толокальные доу = DAY_NUMBER ( день : GSUB ( '[Ss] $' , '' )) - принимать во множественные дниесли не доу, то список возвратаконецoffset = dow - дата . доуконецoperation = ops [ op ]еще список возвратаконецконецсмещение = смещение или 0операция = операция или ОПС [ «>» ]местное datefrom , dayfirst , daylastесли операция . до этогоесли смещение > 0 или ( смещение == 0, а не операция . включить ), тосмещение = смещение - 7конецесли посчитать тоесли count > 1, тосмещение = смещение - 7 * ( количество - 1 )конецdatefrom = дата + смещениеещеdaylast = дата . день + смещениеdayfirst = daylast % 7если dayfirst == 0, тоdayfirst = 7конецконецещеесли смещение < 0 или ( смещение == 0, а не операция . включить ), тосмещение = смещение + 7конецесли посчитать тоdatefrom = дата + смещениеещеdayfirst = дата . день + смещениеdaylast = дата . месячные дниконецконецесли не считать тоесли daylast < dayfirst, то список возвратаконецcount = floor (( daylast - dayfirst ) / 7 ) + 1datefrom = Date ( date , { day = dayfirst })конецдля я = 1 , подсчет делаемесли не datefrom, то break end - превышает лимит датыlist [ i ] = datefromdatefrom = datefrom + 7конец список возвратаконец- Таблица для получения текущей даты / времени (UTC), но только при необходимости.local current = setmetatable ({}, {__index = функция ( сам , ключ )местный d = os.date ( '! * t' )я . год = d . годя . месяц = d . месяця . день = д . денья . час = д . чася . минута = d . миня . второй = d . секвернуть rawget ( self , key )конец })локальная функция extract_date ( новая дата , текст )- Проанализируйте дату / время в тексте и верните n, o где- n = таблица чисел с полями даты / времени- o = таблица опций для AM / PM или AD / BC или формата, если есть- или ничего не вернуть, если известно, что дата недействительна.- Вызывающий абонент определяет, допустимы ли значения в n.- Год должен быть положительным (от «1» до «9999»); используйте "BC" для BC.- В строке ymd год должен состоять из четырех цифр, чтобы избежать двусмысленности.- (от «0001» до «9999»). Единственный способ ввести год <= 0 - указать- дата в виде трех числовых параметров, например ymd Date (-1, 1, 1).- Даты формы д / м / г, м / д / г, г / м / д отклоняются как потенциально неоднозначные.местная дата , options = {}, {}если текст : к югу ( - 1 ) == 'Z' , то- Извлечь дату / время из метки времени Викиданных.- Год может содержать от 1 до 16 цифр, но этот модуль обрабатывает только от 1 до 4 цифр.- Примеры: «+ 2016-06-21T14: 30: 00Z», «-0000000180-00-00T00: 00: 00Z».местный знак , y , m , d , H , M , S = текст : match ( '^ ([+% -]) (% d +)% - (% d% d)% - (% d% d) T ( % d% d): (% d% d): (% d% d) Z $ ' )если подпиши тоу = ToNumber ( у )если sign == '-' и y > 0, тоу = - уконецесли y <= 0, товарианты . era = 'BCE'конецдата . год = yм = ToNumber ( м )д = ToNumber ( д )Н = ToNumber ( Н )М = ToNumber ( М )S = ToNumber ( S )если m == 0, тоновая дата . partial = true дата возврата , вариантыконецдата . месяц = месли d == 0, тоновая дата . partial = true дата возврата , вариантыконецдата . день = десли H > 0 или M > 0 или S > 0, тодата . час = Hдата . минута = Mдата . второй = Sконец дата возврата , вариантыконецвозвращатьсяконецлокальная функция extract_ymd ( элемент )- Вызывается, когда не установлен ни день, ни месяц.local y , m , d = item : match ( '^ (% d% d% d% d)% - (% w +)% - (% d% d?) $' )если у тогдаесли дата . год тогдавозвращатьсяконецесли m : match ( '^% d% d? $' ), том = ToNumber ( м )ещеm = номер_месяца ( м )конецесли м, тодата . год = ToNumber ( у )дата . месяц = мдата . день = ToNumber ( д )вернуть истинуконецконецконецлокальная функция extract_day_or_year ( элемент )- Вызывается, когда день будет действительным, или- когда год будет действительным, если год не установлен, а установлен частичный.местный номер , суффикс = item : match ( '^ (% d% d?% d?% d?) (. *) $' )если число, толокальная п = ToNumber ( число )if # number <= 2 и n <= 31, тосуффикс = суффикс : нижний ()если суффикс == '' или суффикс == 'st' или суффикс == 'nd' или суффикс == 'rd' или суффикс == 'th', тогдадата . день = пвернуть истинуконецelseif суффикс == '' и newdate . частичное, а не свидание . год тогдадата . год = nвернуть истинуконецконецконецлокальная функция extract_month ( элемент )- месяц должен быть указан как название или аббревиатура; число может быть двусмысленным.местный m = номер_месяца ( элемент )если м, тодата . месяц = мвернуть истинуконецконецлокальная функция extract_time ( элемент )local h , m , s = item : match ( '^ (% d% d?): (% d% d) (:?% d *) $' )если дата . час или не ч товозвращатьсяконецесли s ~ = '', тоs = s : match ( '^: (% d% d) $' )если не S , товозвращатьсяконецконецдата . час = ToNumber ( ч )дата . минута = число тонны ( м )дата . second = tonumber ( s ) - ноль, если пустая строкавернуть истинуконецlocal item_count = 0местное index_timeлокальная функция set_ampm ( элемент )местный H = дата . часесли H а не варианты . am и index_time + 1 == item_count, тогдаварианты . am = ampm_options [ item ] - вызывающий проверил, что это не нольесли item : match ( '^ [Aa]' ), тоесли нет ( 1 <= H и H <= 12 ), товозвращатьсяконецесли H == 12, тодата . час = 0конецещеесли нет ( 1 <= H и H <= 23 ), товозвращатьсяконецесли H <= 11, тодата . час = H + 12конецконецвернуть истинуконецконецдля элемента в тексте : gsub ( ',' , '' ): gsub ( '& nbsp;' , '' ): gmatch ( '% S +' ) doitem_count = item_count + 1если era_text [ элемент ], то- Эра принимается в своеобразных местах.если варианты . эра тогдавозвращатьсяконецварианты . эпоха = предметelseif ampm_options [ элемент ] тогдаесли не set_ampm ( item ), товозвращатьсяконецelseif item : find ( ':' , 1 , true ) затемесли не extract_time ( элемент ), товозвращатьсяконецindex_time = item_countelseif дата . день и дату . месяц тогдаесли дата . год тогдаreturn - больше ничего не должно быть, значит, предмет недействителенконецесли не item : match ( '^ (% d% d?% d?% d?) $' ) товозвращатьсяконецдата . год = ToNumber ( пункт )elseif дата . день тогдаесли не extract_month ( элемент ), товозвращатьсяконецelseif дата . месяц тогдаесли не extract_day_or_year ( элемент ), товозвращатьсяконецelseif extract_month ( элемент ) тогдаварианты . format = 'mdy'elseif extract_ymd ( элемент ) тогдаварианты . format = 'ymd'elseif extract_day_or_year ( элемент ) тогдаесли дата . день тогдаварианты . format = 'dmy'конецещевозвращатьсяконецконецесли не дата . год или дату . год == 0 тогдавозвращатьсяконецместная эра = эра_текст [ параметры . эпоха ]если эпоха и эпоха . isbc тогдадата . год = 1 - дата . годконец дата возврата , вариантыконецлокальная функция автозаполнения ( date1 , дата2 )- Заполните любой пропущенный месяц или день каждой даты, используя- соответствующий компонент с другой даты, если он присутствует,- или с 1, если в обеих датах отсутствует месяц или день.- Это дает хороший результат для расчета разницы- между двумя неполными датами, когда диапазон не нужен.- Возврат заполнен date1, date2 (две полные даты).локальная функция заполнена ( a , b )- Дата возврата a, если необходимо, с указанием месяца и / или числа с даты b.- Заполненный день усекается, чтобы соответствовать количеству дней в месяце.местный месяц , день заполненияесли не a . месяц тогдаfillmonth = b . месяц или 1конецесли не . день тогда fillday = b . день или 1конецесли fillmonth или fillday тогда - нужно создать новую датуa = Дата ( a , {month = fillmonth ,day = math.min ( fillday или a . day , days_in_month ( a . year , fillmonth или a . month , a . calendar ))})конецвозвращение конецвернуть заполненный ( DATE1 , date2 ), заполненный ( date2 , date1 )конецлокальная функция date_add_sub ( LHS , RHS , is_sub )- Вернуть новую дату из расчета (lhs + rhs) или (lhs - rhs),- или ничего не вернуть, если он недействителен.- Результат равен нулю, если рассчитанная дата превышает допустимые пределы.- Caller гарантирует, что lhs - это дата; его свойства копируются на новую дату.если lhs . частичный тогда- Добавление к частичному не поддерживается.- Можно вычесть дату или часть из части, но для этого это не требуется.возвращатьсяконецлокальная функция is_prefix ( текст , слово , минлен )местный n = # текстreturn ( minlen или 1 ) <= n и n <= # слово и текст == word : sub ( 1 , n )конецлокальная функция do_days ( n )местный forcetime , юлианский деньесли floor ( n ) == n, тоjd = lhs . jdещеforcetime = not lhs . времяjd = lhs . jdzконецjd = jd + ( is_sub и - n или n )если forcetime тогдаJD = ToString ( JD )если не jd : find ( '.' , 1 , true ), тоjd = jd .. '.0'конецконец Дата возврата ( lhs , 'juliandate' , jd )конецесли type ( rhs ) == 'number', то- Добавить / вычесть дни, включая дробные дни.возврат do_days ( rhs )конецесли type ( rhs ) == 'string', то- правая часть - это один компонент, например «26 месяцев» или «26 месяцев» (с необязательным знаком).- Доли типа «3.25d» принимаются для единиц, которые обрабатываются как дни.локальный знак , numstr , id = rhs : match ( '^% s * ([+ -]?) ([% d%.] +)% s * (% a +) $' )если подпиши тоесли знак == '-' тоis_sub = not ( is_sub и истина или ложь )конецместное г , м , днилокальная Num = ToNumber ( NumStr )если не число, товозвращатьсяконецid = id : нижний ()если is_prefix ( id , 'years' ), тоy = числот = 0elseif is_prefix ( id , 'months' ) тогдаy = этаж ( число / 12 )m = число % 12elseif is_prefix ( id , 'weeks' ) тогдадней = число * 7elseif is_prefix ( id , 'days' ) тогдадней = числоelseif is_prefix ( id , 'часы' ) тогдадней = число / 24elseif is_prefix ( id , 'minutes' , 3 ), тодней = число / ( 24 * 60 )elseif is_prefix ( id , 'секунды' ) тогдадней = число / ( 24 * 3600 )ещевозвращатьсяконецесли дни тоreturn do_days ( дни )конецесли numstr : find ( '.' , 1 , true ), товозвращатьсяконецесли is_sub, тоу = - ум = - мконецassert ( - 11 <= m и m <= 11 )y = lhs . год + гм = лев . месяц + месли m > 12, тоу = у + 1м = м - 12иначе, если m < 1, тоу = у - 1м = м + 12конецместный г = Math.min ( LHS . день , Days_in_Month ( у , м , LHS . календарь )) Дата возврата ( lhs , y , m , d )конецконецесли is_diff ( rhs ), томестные дни = прав . age_daysif ( is_sub или false ) ~ = ( rhs . isnegative или false ), тоdays = - дниконецвозврат lhs + днейконецконецlocal full_date_only = {dayabbr = правда ,dayname = true ,dow = true ,dayofweek = правда ,dowiso = истина ,dayofweekiso = правда ,dayofyear = правда ,gsd = true ,juliandate = правда ,jd = истина ,jdz = истина ,jdnoon = правда ,}- Метатаблица для вычисляемых полей даты.local datemt = {__index = функция ( сам , ключ )если rawget ( self , 'partial' ), тоесли full_date_only [ ключ ], то вернуть конецесли key == 'monthabbr' или key == 'monthdays' или key == 'monthname', тогдаесли не сам . месяц, затем конец возврата конецконецместная ценностьесли ключ == 'dayabbr', тогдазначение = day_info [ self . доу ] [ 1 ]elseif key == 'dayname' тогдазначение = day_info [ self . доу ] [ 2 ]elseif key == 'dow', затемзначение = ( self . jdnoon + 1 ) % 7 - день недели 0 = с воскресенья по 6 = сбelseif key == 'dayofweek' тогдазначение = себя . доуelseif key == 'dowiso' тогдаvalue = ( self . jdnoon % 7 ) + 1 - день недели по ISO 1 = с понедельника по 7 = всelseif key == 'dayofweekiso' тогдазначение = себя . Dowisoelseif key == 'dayofyear' тогдаlocal first = Дата ( сам . год , 1 , 1 , сам . календарь ). пнзначение = себя . jdnoon - первый + 1 - день года от 1 до 366elseif key == 'era' тогда- Текст эпохи (никогда не отрицательный) с годом и вариантами.значение = get_era_for_year ( сам . параметры . эра , сам . год )elseif key == 'format' затемзначение = себя . варианты . формат или dmyelseif key == 'gsd' тогда- GSD = 1 с 00:00:00 до 23:59:59 1 января 1 января нашей эры по григорианскому календарю,- что составляет от 1721425,5 до 1721426,49999.Значение = пол ( самостоятельно . JD - 1721424,5 )elseif key == 'juliandate' или key == 'jd' или key == 'jdz', тогдалокальная JD , JDZ = julian_date ( само )rawset ( self , 'juliandate' , jd )rawset ( сам , 'jd' , jd )rawset ( сам , 'jdz' , jdz )возвращение ключ == «JDZ» и JDZ или юлианский деньelseif key == 'jdnoon' тогда- полдень по юлианскому календарю (целое число) календарного дня, когда наступает jd.значение = этаж ( self . jd + 0,5 )elseif key == 'isleapyear' тогдазначение = is_leap_year ( сам . год , самостоятельно . календарь )elseif key == 'monthabbr' тогдазначение = month_info [ self . месяц ] [ 1 ]elseif key == 'monthdays', затемзначение = дней_в_месяц ( сам . год , сам . месяц , сам . календарь )elseif key == 'monthname', затемзначение = month_info [ self . месяц ] [ 2 ]конецесли значение ~ = nil, тоrawset ( собственный , ключ , значение )возвращаемое значениеконецконец ,}- Операторы даты.локальная функция mt_date_add ( LHS , шк )если не is_date ( LHS ) , тоlhs , rhs = rhs , lhs - поставить дату слева (это должна быть дата, чтобы это было вызвано)конецВозвращение date_add_sub ( LHS , шк )конецлокальная функция mt_date_sub ( LHS , шк )если is_date ( LHS ) , тоесли is_date ( rhs ), тоВозвращение DateDiff ( LHS , шк )конецВозвращение date_add_sub ( LHS , шк , правда )конецконецлокальная функция mt_date_concat ( LHS , шк )возвращение ToString ( LHS ) .. ToString ( шк )конецлокальная функция mt_date_tostring ( self )вернуть себя : текст ()конецлокальная функция mt_date_eq ( LHS , шк )- Вернуть истину, если даты идентифицируют одну и ту же дату / время, где, например,- Date (-4712, 1, 1, 'Julian') == Date (-4713, 11, 24, 'Gregorian') верно.- Это вызывается, только если lhs и rhs имеют один и тот же тип и один и тот же метаметод.если lhs . частичный или правый . частичный тогда- Одно свидание неполное; другой - частичное или полное свидание.- Оба месяца могут быть нулевыми, но должны быть одинаковыми.вернуть lhs . год == правый . год и лев . месяц == прав . месяц и lhs . календарь == правый . календарьконецвернуть lhs . jdz == rhs . jdzконецлокальная функция mt_date_lt ( LHS , шк )- Вернуть истину, если lhs <rhs, например,- Дата ('1 января 2016') <Дата ('06: 00 1 января 2016 ') верно.- Это вызывается, только если lhs и rhs имеют один и тот же тип и один и тот же метаметод.если lhs . частичный или правый . частичный тогда- Одно свидание неполное; другой - частичное или полное свидание.если lhs . календарь ~ = прав . календарь тогдавернуть lhs . календарь == 'юлианский'конецесли lhs . частичный тогдаlhs = lhs . частичный . первыйконецесли ОРЗ . частичный тогдаrhs = rhs . частичный . первыйконецконецвернуть lhs . jdz < rhs . jdzконец- [[Примеры синтаксиса для построения даты:Дата (г, м, д, 'julian') календарь по умолчанию - 'грегорианский'Дата (г, м, д, H, M, S, 'julian')Date ('juliandate', jd, 'julian'), если jd содержит "." текстовый вывод включает H: M: SДата ('текущая дата')Дата ('currentdatetime')Date ('1 апреля 1995', 'julian') разобрать дату из текстаDate ('1 апреля 1995 г. н.э.', 'julian') с использованием эры устанавливает флаг, чтобы сделать то же самое для выводаДата ('04: 30: 59 1 апреля 1995 ',' julian ')Дата (дата) копия существующей датыДата (дата, t) такая же, обновлена полями y, m, d, H, M, S из таблицы tDate (t) дата с полями y, m, d, H, M, S из таблицы t]]функция Date (...) - для форвардного объявления выше- Вернуть таблицу с датой, предполагая, что всегда применяется единый календарь- (пролептический григорианский календарь или пролептический юлианский календарь), или- ничего не возвращать, если дата недействительна.- Неполная дата имеет действительный год, однако ее месяц может быть нулевым, и- его поля дня и времени равны нулю.- Частичное поле имеет значение false (если полная дата) или таблица (если частичная дата).местные календари = { julian = 'Julian' , gregorian = 'Gregorian' }local newdate = {_id = uniq ,calendar = 'Gregorian' , - по умолчанию григорианский календарьhastime = false , - истина, если ввод устанавливает времяhour = 0 , - всегда устанавливается час / минута / секунда, поэтому не нужно обрабатывать нольминута = 0 ,второй = 0 ,options = {},list = _date_list ,вычитание = функция ( self , rhs , options )return DateDiff ( self , rhs , параметры )конец ,text = _date_text ,}местный тип аргумент , datetext , is_copy , jd_number , tnumsместный numindex = 0local numfields = { 'год' , 'месяц' , 'день' , 'час' , 'минута' , 'секунда' }местные номера = {}для _ , v в ipairs ({...}) сделатьv = strip_to_nil ( v )local vlower = type ( v ) == 'строка' и v : lower () или nilесли v == nil, то- Игнорировать пустые аргументы после удаления, чтобы модули могли напрямую передавать параметры шаблона.elseif календари [ vlower ] тогдановая дата . calendar = календари [ vlower ]elseif vlower == 'partial' тогдановая дата . partial = trueelseif vlower == 'fix' тогдановая дата . want_fix = trueElseIf is_date ( v ) , то- Копировать существующую дату (элементы могут быть отменены другими аргументами).если is_copy или tnums, товозвращатьсяконецis_copy = истинановая дата . календарь = v . календарьновая дата . частичный = v . частичныйновая дата . hastime = v . времяновая дата . параметры = v . опцииновая дата . год = v . годновая дата . месяц = v . месяцновая дата . день = v . деньновая дата . час = v . часновая дата . минута = v . минутановая дата . второй = v . второйelseif type ( v ) == 'table' тогдаесли tnums, товозвращатьсяконецtnums = {}local tfields = { год = 1 , месяц = 1 , день = 1 , час = 2 , минута = 2 , секунда = 2 }для tk , tv в парах ( v ) делатьесли tfields [ tk ], тоtnums [ тк ] = ToNumber ( тв )конецесли tfields [ tk ] == 2, тоновая дата . hastime = trueконецконецещелокальная Num = ToNumber ( v )если не num и argtype == 'setdate' и numindex == 1, точисло = номер_месяца ( v )конецесли число, тоесли не argtype, тоargtype = 'установленная дата'конецесли argtype == 'setdate' и numindex < 6, тогдануминдекс = нуминдекс + 1числа [ numfields [ numindex ]] = числоelseif argtype == 'juliandate', а не jd_number, тогдаjd_number = числоесли type ( v ) == 'строка', тоесли v : find ( '.' , 1 , true ), тоновая дата . hastime = trueконецelseif num ~ = floor ( num ) тогда- Данное значение было числом. Время будет использовано- если дробная часть отлична от нуля.новая дата . hastime = trueконецещевозвращатьсяконецelseif argtype тогдавозвращатьсяelseif type ( v ) == 'строка' тогдаесли v == 'currentdate' или v == 'currentdatetime' или v == 'juliandate', тогдаargtype = vещеargtype = 'datetext'datetext = vконецещевозвращатьсяконецконецконецесли argtype == 'datetext', тогдаесли tnums или нет set_date_from_numbers ( newdate , extract_date ( newdate , datetext )), товозвращатьсяконецelseif argtype == 'juliandate' тогдановая дата . частичный = нольновая дата . JD = jd_numberесли не set_date_from_jd ( newdate ), товозвращатьсяконецelseif argtype == 'currentdate' или argtype == 'currentdatetime', тогдановая дата . частичный = нольновая дата . год = текущий . годновая дата . месяц = текущий . месяцновая дата . день = текущий . деньесли argtype == 'currentdatetime', тогдановая дата . час = текущий . часновая дата . минута = текущая . минутановая дата . второй = текущий . второйновая дата . hastime = trueконецновая дата . calendar = 'Gregorian' - игнорировать любое указанное название календаряelseif argtype == 'setdate', затемесли tnums или нет set_date_from_numbers ( newdate , numbers ), товозвращатьсяконециначе, если нет ( is_copy или tnums ), товозвращатьсяконецесли tnums, тоновая дата . jd = nil - принудительный пересчет в случае, если jd был установлен до изменения tnumsесли не set_date_from_numbers ( newdate , tnums ), товозвращатьсяконецконецесли newdate . частичный тогдаместный год = новая дата . годместный месяц = новая дата . месяцlocal first = Дата ( год , месяц или 1 , 1 , новая дата . календарь )месяц = месяц или 12local last = Дата ( год , месяц , days_in_month ( год , месяц ), новая дата . календарь )новая дата . частичный = { первый = первый , последний = последний }ещеновая дата . partial = false - избегать поиска по индексуконецsetmetatable ( newdate , datemt )local readonly = {}local mt = {__index = newdate ,__newindex = function ( t , k , v ) error ( 'date.' .. tostring ( k ) .. 'только для чтения' , 2 ) end ,__add = mt_date_add ,__sub = mt_date_sub ,__concat = mt_date_concat ,__tostring = mt_date_tostring ,__eq = mt_date_eq ,__lt = mt_date_lt ,}Возвращение setmetatable ( только для чтения , т )конецлокальная функция _diff_age ( дифф , код , опция )- Вернуть кортеж целых значений из diff, как указано в коде, за исключением того, что- каждое целое число может быть списком из двух целых чисел для сравнения с частичной датой, или- вернуть nil, если код не поддерживается.- Если хотите округлить, наименее значимая единица округляется до ближайшей целой единицы.- На время добавляется дополнительный день.местный wantround , wantduration , wantrangeесли type ( options ) == 'table', тоwantround = варианты . круглыйwantduration = варианты . продолжительностьwantrange = варианты . классифицироватьещеwantround = вариантыконецесли не is_diff ( diff ), томестный f = wantduration и 'продолжительность' или 'возраст'error ( f .. ': нужна разница в датах (используйте "diff:' .. f .. '()" с двоеточием)' , 2 )конецесли разн . частичный тогда- Игнорируйте бессмысленность, желаемую продолжительность.локальная функция choose ( v )если type ( v ) == 'table', тоесли не wantrange или v [ 1 ] == v [ 2 ], то- Пример: Дата («частично», 2005 г.) - «Дата (« частично », 2001 г.) дает- diff.years = {3, 4}, чтобы показать диапазон возможных результатов.- Если диапазон не нужен, выберите второе значение как более ожидаемое.вернуть v [ 2 ]конецконецвернуть vконецесли code == 'ym' или code == 'ymd', тогдаесли не хотите ранжировать и разн . равно нулю тогда- Это позволяет избежать неожиданного результата, такого как- Дата («частично», 2001 г.) - Дата («частично», 2001 г.)- давая diff = {years = 0, months = {0, 11}}- что будет указано как 0 лет и 11 месяцев.возврат 0 , 0конецобратный выбор ( разна . частичные . года ), выберите ( разна . частичные . месяцы )конецесли code == 'y' тогдавозврат выбрать ( разн . част . лет )конецесли code == 'm' или code == 'w' или code == 'd', тогдаВозвращение выбрать ({ диф . парциальное . mindiff : возраст ( код ), диф . парциальное . maxdiff : возраст ( код ) })конецвернуть нольконецместные extra_days = wantduration и 1 или 0если code == 'wd' или code == 'w' или code == 'd', тогдалокальное смещение = wantround и 0,5 или 0местные дни = разн . age_days + extra_daysесли code == 'wd' или code == 'd', тодни = этаж ( дни + смещение )если code == 'd' тогда дни возвратаконецвозвратный этаж ( дней / 7 ), дней % 7конецвозвратный этаж ( дней / 7 + зачет )конецместный H , M , S = разн . часов , разн . минут , разн . секундыесли code == 'dh' или code == 'dhm' или code == 'dhms' или code == 'h' или code == 'hm' или code == 'hms' или code == 'M' или code == 's' тогдаместные дни = этаж ( разн . возраст_дней + дополнительные_дни )местный inc_hourесли хотите, тоесли code == 'dh' или code == 'h', тогдаесли M > = 30, тоinc_hour = правдаконецelseif code == 'dhm' или code == 'hm' тогдаесли S > = 30, тоМ = М + 1если M > = 60, тоM = 0inc_hour = правдаконецконецelseif code == 'M' тогдаесли S > = 30, тоМ = М + 1конецеще- Ничего не нужно, потому что S - целое число.конецесли inc_hour, тоH = H + 1если H > = 24, тоH = 0дни = дни + 1конецконецконецесли code == 'dh' или code == 'dhm' или code == 'dhms', тогдаесли code == 'dh' тогда дней возврата , Чelseif code == 'dhm' тогдавозвратные дней , H , Mеще дни возврата , H , M , Sконецконецместные часы = дни * 24 + Hесли code == 'h' тогда часы возвратаelseif code == 'hm' тогда часы возврата , Мelseif code == 'M' или code == 's' тогдаM = часы * 60 + Mесли code == 'M', тогдавернуть Mконецвернуть M * 60 + Sконец часы возврата , M , Sконецесли хотите, томестный inc_hourесли code == 'ymdh' или code == 'ymwdh' тогдаесли M > = 30, тоinc_hour = правдаконецelseif code == 'ymdhm' или code == 'ymwdhm' тогдаесли S > = 30, тоМ = М + 1если M > = 60, тоM = 0inc_hour = правдаконецконецelseif code == 'ymd' или code == 'ymwd' или code == 'yd' или code == 'md' тогдаесли H > = 12, тоextra_days = extra_days + 1конецконецесли inc_hour, тоH = H + 1если H > = 24, тоH = 0extra_days = extra_days + 1конецконецконецлокальный y , m , d = diff . лет , разн . месяцев , разн . днейесли extra_days > 0, тоd = d + extra_daysесли d > 28 или code == 'yd', тогда- Пересчитать, если прошел месяц.разн = разн . date1 + extra_days - разн . date2y , m , d = разн . лет , разн . месяцев , разн . днейконецконецесли code == 'ymd' тогдавозврат y , m , delseif code == 'yd' тогдаесли y > 0, то- Известно, что diff.date1> diff.date2.разн = разн . date1 - ( разн . date2 + ( у .. 'у' ))конецвозвращение у , пол ( разн . age_days )elseif code == 'md' тогдавозврат y * 12 + m , delseif code == 'ym' или code == 'm' тогдаесли хотите, тоесли d > = 16, том = м + 1если m > = 12, тот = 0у = у + 1конецконецконецесли code == 'ym' тогдавозврат г , мконецвозврат y * 12 + melseif code == 'ymw' тогдаместные недели = этаж ( д / 7 )если хотите, томестные дни = d % 7если дней > 3 или ( дней == 3 и H > = 12 ), тонедели = недели + 1конецконецвозврат г , м , неделиelseif code == 'ymwd' тогдадоходность г , м , этаж ( д / 7 ), д % 7elseif code == 'ymdh' тогдавозврат y , m , d , Helseif code == 'ymwdh' тогдадоходность y , м , этаж ( д / 7 ), д % 7 , Helseif code == 'ymdhm' тогдавозврат y , m , d , H , Melseif code == 'ymwdhm' тогдадоходность y , м , этаж ( д / 7 ), д % 7 , H , Mконецесли code == 'y' тогдаесли wantround и m > = 6, тоу = у + 1конецвернуть yконецвернуть нольконецлокальная функция _diff_duration ( дифф , код , опция )если type ( options ) ~ = 'table', тоoptions = { round = options }конецварианты . продолжительность = правдаВозвращение _diff_age ( дифф , код , опция )конец- Метатаблица для некоторых операций с разницей в датах.diffmt = { - для предварительного объявления выше__concat = функция ( LHS , шк )возвращение ToString ( LHS ) .. ToString ( шк )конец ,__tostring = функция ( сам )вернуться в строку ( self . age_days )конец ,__index = функция ( сам , ключ )местная ценностьесли ключ == 'age_days', тоесли rawget ( self , 'partial' ), толокальная функция jdz ( дата )возврат ( дата . частичная и дата . частичная . первая или дата ). jdzконецзначение = jdz ( self . date1 ) - jdz ( self . date2 )ещезначение = себя . дата1 . jdz - сам . дата2 . jdzконецконецесли значение ~ = nil, тоrawset ( собственный , ключ , значение )возвращаемое значениеконецконец ,}Функция DateDiff ( DATE1 , date2 , варианты ) - для прямой декларации выше- Вернуть таблицу с разницей между двумя датами (date1 - date2).- Разница отрицательная, если date1 старше date2.- Ничего не возвращать, если недействителен.- Если d = date1 - date2, то- date1 = date2 + d- Если date1> = date2 и в датах не указано время H: M: S, тогда- date1 = date2 + (d.years .. 'y') + (d.months .. 'm') + d.days- где сначала добавляются большие единицы времени.- Результат Date (2015,1, x) + '1m' равен Date (2015,2,28) для- x = 28, 29, 30, 31. Это означает, например,- d = Дата (2015,3,3) - Дата (2015,1,31)- дает d.years, d.months, d.days = 0, 1, 3 (исключая date1).если не ( is_date ( date1 ) и is_date ( дата2 ) и date1 . календарь == дата2 . календарь ) , товозвращатьсяконецместные нуждыесли type ( options ) == 'table', тоwantfill = options . наполнятьконецlocal isnegative = ложьместный iszero = falseесли date1 < date2 затемisnegative = правдаdate1 , дата2 = дата2 , date1ElseIf date1 == date2 затемiszero = trueконец- Известно, что date1> = date2 (период от date2 до date1).если date1 . частичное или дата2 . частичный тогда- Две частичные даты могут иметь временные рамки:--------------------- A ================= B --- date1 от A до B включительно-------- C ======= D -------------------------- date2 от C до D включительно- date1> date2 iff A> C (date1.partial.first> date2.partial.first)- Периоды могут перекрываться («апрель 2001» - «2001»):------------- A === B ------------------------- A = 2001-04-01 B = 2001-04-30-------- C ===================== D ------------ C = 2001-01-01 D = 31 декабря 2001 г.если хотите, то заполнитеdate1 , дата2 = автозаполнение ( date1 , дата2 )ещелокальная функция zdiff ( date1 , дата2 )локальная дифф = date1 - date2если разн . тогда отрицательно return date1 - date1 - действительный diff в случае, если мы вызываем его методыконецвернуть разницуконецлокальная функция getdate ( дата , которая ) дата возврата . частичная и дата . частичный [ который ] или датаконецлокальная maxdiff = zdiff ( GETDATE ( date1 , 'последний' ), GETDATE ( date2 , 'первый' ))локальная mindiff = zdiff ( GETDATE ( date1 , 'первый' ), GETDATE ( date2 , 'последний' ))местные годы , месяцыесли maxdiff . лет == миндифф . лет тогдалет = максдифф . годыесли maxdiff . месяцев == mindiff . месяцев тогдамесяцев = maxdiff . месяцыещемесяцев = { mindiff . месяцев , maxdiff . месяцев }конецещелет = { mindiff . лет , maxdiff . лет }конецreturn setmetatable ({date1 = date1 ,дата2 = дата2 ,partial = {годы = годы ,месяцы = месяцы ,максдифф = максдифф ,mindiff = mindiff ,},isnegative = isnegative ,iszero = iszero ,возраст = _diff_age ,duration = _diff_duration ,}, diffmt )конецконецлокальный y1 , m1 = date1 . год , дата1 . месяцлокальный y2 , m2 = date2 . год , дата2 . месяцместные годы = y1 - y2местные месяцы = m1 - m2местный d1 = date1 . день + hms ( date1 )местный d2 = date2 . день + HMS ( date2 )местные дни , времяесли d1 > = d2, тодней = d1 - d2ещемесяцы = месяцы - 1- Получить дни в предыдущем месяце (до даты «до»), поскольку в декабре 31 день.local dpm = m1 > 1 и days_in_month ( y1 , m1 - 1 , date1 . calendar ) или 31если d2 > = dpm, тодней = d1 - HMS ( date2 )ещедни = dpm - d2 + d1конецконецесли месяцев < 0, толет = лет - 1месяцев = месяцев + 12конецdays , time = math.modf ( дни )местное H , M , S = h_m_s ( время )return setmetatable ({date1 = date1 ,дата2 = дата2 ,partial = false , - избегать поиска по индексугоды = годы ,месяцы = месяцы ,days = дни ,часы = H ,минут = M ,секунды = S ,isnegative = isnegative ,iszero = iszero ,возраст = _diff_age ,duration = _diff_duration ,}, diffmt )конецreturn {_current = ток ,_Date = Дата ,_days_in_month = days_in_month ,}