Работа с датами и временем


Помимо традиционного формата указания даты (YMD, YMDHMS, в строках или в числовом представлении), nnCron работает и с двумя другими представлениями дат: DATE и FILETIME.

DATE - это число, которое в двоичном представлении выглядит так: гггггггггггммммддддд, т. е. пять младших разрядов занимает день, четыре следующих - месяц, а все остальное год. Из этого следует, что DATE содержит только информацию о годе, месяце и числе. Информация о часах, минутах и секундах не хранится. Формат DATE используют, например, слова FILE-CREATION-DATE:, FILE-ACCESS-DATE:, FILE-WRITE-DATE:, а также слова, употребляемые внутри цикла FOR-FILES: (CREATION-DATE, ACCESS-DATE, WRITE-DATE).

FILETIME позволяет оперировать не только со значениями года, месяца и числа, но и с часами, минутами, секундами и даже миллисекундами. FILETIME - число двойной длины, которое содержит количество 100-наносекндных интервалов, прошедших с 1-го января 1601 года до времени указанной даты. Формат FILETIME используют, например, слова из плагина time.spf (FILE-TIME:, FILE-ATIME:, FILE-WTIME:). При работе с датами и временем мы рекомендуем использовать именно формат FILETIME.

При необходимости вы можете конвертировать даты между форматами YMD, DATE и FILETIME.



ASSUMED-NEXT-TIME ( -- d t= | -- f= )
ASSUMED-PREV-TIME ( -- d t= | -- f= )

При использовании внутри задачи, эти слова позволяют получить доступ к информации о предполагаемом времени следующего и предыдущего запусков текущей задачи.

Слово ASSUMED-NEXT-TIME возвращает флаг TRUE и предполагаемое время следующего планируемого запуска задачи либо просто флаг FALSE, если программе не удается вычислить время. Слово ASSUMED-PREV-TIME возвращает флаг TRUE и предполагаемое время предыдущего запуска задачи (даже если оно было просрочено) или флаг FALSE, если программе не удается вычислить время.

Оба слова возвращает время в формате FILETIME.

Примеры:

#( test_assumed_time 
\ каждые две минуты выводим на консоль 
\ предполагаемое время следующего запуска задачи
Time: */2
Action:
    ASSUMED-NEXT-TIME 
    IF
        FT>DD.MM.YYYY/hh:mm:ss TYPE CR 
    THEN
)#

#( test_assumed_time1
\ создаем специальные слова и каждые три минуты 
\ выводим на консоль предполагаемое время предыдущего
\ и следующего запуска задачи
: FT. FT>DD.MM.YYYY/hh:mm:ss TYPE ;
: ?FT. IF FT. ELSE ." none" THEN ;
Time: */3
Action:
   ASSUMED-NEXT-TIME ?FT. CR
   ASSUMED-PREV-TIME ?FT. CR
)#

CUR-DATE ( -- u )

Кладет на стек значение текущей даты (в формате DATE). Используется для сравнения произвольных дат, например даты создания/последнего доступа/последней записи в файл с текущей датой (подробнее).


DATE>S ( u -- a u )

Преобразует дату в формате DATE в строку "DD-MM-YYYY".

Примеры:

\ выводим текущую дату на консоль
CUR-DATE DATE>S TYPE

#( test_message
NoActive Action: \ выводим текущую дату в сообщении MSG: "Current date: %CUR-DATE DATE>S%" )#

DATE- ( u1 u2 -- u )

Возвращает разницу в днях между двумя датами в формате DATE.

Пример:

\ кладем на стек значение текущей даты
CUR-DATE
\ преобразуем дату "31 декабря 2002" в формат DATE
2002 12 31 YMD>DATE
\ вычисляем разницу (в днях) между этими двумя датами
DATE- . CR

DATE-INTERVAL: dd1.mm1.yyyy1-dd2.mm2.yyyy2[/days]

Возвращает флаг TRUE (-1), если текущая дата попадает в указанный интервал.
Дополнительный (необязательный) параметр, указывающийся через косую черту, определяет "шаг срабатывания" условия: (количество дней, прошедших с начала интервала кратно периоду days).

См. также: INTERVAL: hh1:mm1-hh2:mm2[/hh3:mm3]


DAY+ ( y m d days -- y1 m1 d1 )

Это слово позволяет "добавить" или "отнять" произвольное количество дней у даты, указанной в формате YMD и получить результат в этом же формате, с учетом количества дней в месяце и количества месяцев в году.

Пример:

\ добавляем один день к дате "31 декабря 2002",
\ выводим на консоль результат ("1 января 2003").
2002 12 31 1 DAY+ . . . CR

Используйте отрицательное значение, чтобы "вычесть" определенное количество дней.

Пример:

\ вычитаем один день из даты "31 декабря 2002",
\ выводим на консоль результат ("30 декабря 2002").
2002 12 31 -1 DAY+ . . . CR

DAYS ( y m d -- days )

Кладет на стек количество дней, прошедших от начала летоисчисления по григорианскому календарю до указанной даты. В качестве аргумента принимает дату в формате YMD.

Пример:

\ выводим на консоль количество дней,
\ прошедших до 1 января 2003
2003 1 1 DAYS . CR

Days@

Кладет на стек количество дней, прошедших от начала летоисчисления по григорианскому календарю до текущей даты.


FT-

Возвращает разницу между двумя датами в формате FILETIME. Чтобы перевести полученное значение, например, в секунды, воспользуйтесь словом FT>SEC.

Пример:

\ дважды "засекаем" время и кладем на стек
\ разницу между двумя датами в секундах
FT-CUR
10000 PAUSE
FT-CUR FT- FT>SEC D>S . CR


FT-CUR

Конвертирует текущие дату и время в формат FILETIME.

Пример:

#( test_file_time
\ если файл '1.sem' создан больше двух минут назад,
\ производим какие-то полезные действия
Action:
FT-CUR FILE-TIME: "C:\1.sem" FTIME- 120 >
IF
    \ ... производим работу
THEN
)#


FT>DAY
FT>HOUR
FT>MIN

Конвертирует указанную дату и время в формате FILETIME в количество дней, часов и минут соответственно.


FT>DD.MM.YYYY/hh:mm:ss ( d - a u)

Конвертирует указанную дату и время в формате FILETIME в строку "DD.MM.YYYY/hh:mm:ss".

Пример:

\ выводим на консоль текущую дату и время (31.03.3003/14:40:47)
FT-CUR FT>DD.MM.YYYY/hh:mm:ss TYPE CR

FT>MS
FT>SEC

Конвертирует указанную дату и время в формате FILETIME в миллисекунды и секунды соответственно. Возвращает число двойной длины.


GET-CUR-TIME

Принудительно "обновляет" значение текущего времени. nnCron делает это автоматически один раз в минуту и, соответственно, значения секунд в течение минуты больше не обновляются. Используйте GET-CUR-TIME, чтобы обновить значение секунд принудительно.

Примеры:

\ на пpотяжении минуты (pаз в секунду)
\ пишем точное текущее вpемя в лог-файл:
#( test_cur_time
NoActive
Action:
    60 0 DO
    GET-CUR-TIME
    LOG: "log\idle.log" "%hh%:%mm%:%ss% - current time"
    PAUSE: 1000
    LOOP
)#
   
\ выводим на консоль точное значение текущей секунды
GET-CUR-TIME Sec@

GetTickCount

Кладет на стек количество миллисекунд, прошедших с момента старта операционной системы. GetTickCount - это системная функция, которая возвращает число одинарной длины со знаком. Это означает, что через 49,7 дней непрерывной работы компьютера значение GetTickCount переполнится и снова начнет отсчитываться с нуля.

Пример:

\ задача запустится, если с момента старта 
\ операционной системы прошло меньше 90 секунд
Rule: GetTickCount 90000 <

См. также: UPTIME


INTERVAL: hh1:mm1-hh2:mm2[/hh3:mm3]

Возвращает флаг TRUE (-1), если текущее время попадает в указанный интервал.
Дополнительный (необязательный) параметр, указывающийся через косую черту определяет "шаг срабатывания" условия: (время, прошедшее от начала интервала, кратно периоду hh3:mm3).

\ возвратит 'TRUE' в 10:00, 10:45 и 11:30 
\ (т. е. через каждые 45 минут)
Rule: INTERVAL: 10:00-12:00/00:45
\ возвратит 'TRUE' в 10:00, 11:01, 12:02 и 13:03 
\ (т. е. раз в 61-ну минуту)
Rule: INTERVAL: 10:00-14:00/01:01

Примеры:

#( test_interval
WatchConnect
Rule: INTERVAL: 10:00-18:00
Action:
    \ ... выполняем работу
)#
#( test_interval1 \ срабатываем раз в 30 минут с 10:00 до 18:00 включительно Rule: INTERVAL: 10:00-18:00/00:30 Action: MSG: "Прошло полчаса!" )#

См. также: DATE-INTERVAL: dd1.mm1.yyyy1-dd2.mm2.yyyy2[/days]


FT>DATE
FT>YMDHMS
DATE>YMD
YMD>DATE
YMDHMS>FT

Эти слова конвертируют даты между форматами YMD (YMDHMS), DATE и FILETIME.

Примеры:

\ FILETIME в DATE
FT-CUR FT>DATE
\ FILETIME в YMDHMS
FT-CUR FT>YMDHMS
\ DATE в YMD
CUR-DATE DATE>YMD
\ YMD в DATE
2002 12 31 YMD>DATE
\ YMDHMS в FILETIME
2002 12 31 0 0 0 YMDHMS>FT

Sec@
Min@
Hour@
Day@
Mon@
WDay@
Year@

Эти слова кладут на стек текущее значение секунды, минуты, часа, дня, месяца, дня недели и года. Обратите внимание, что для получения корректного текущего значения секунд вам придется воспользоваться словом GET-CUR-TIME.

Пример:

\ кладем на стек текущую дату в формате YMD
Year@ Mon@ Day@
\ кладем на стек текущую дату в формате YMDHMS
Year@ Mon@ Day@ Hour@ Min@ GET-CUR-TIME Sec@

MonLength ( year month -- days-of-month )

Возвращает количество дней в указанном месяце. В качестве аргументов принимает год и порядковый номер нужного месяца.

Пример:

\ выводим на консоль количество дней в феврале 2003
2003 2 MonLength . CR

WDAYS
MONNAMES

Эти предопределенные массивы содержат сокращенные названия дней недели и месяцев. WDAYS содержит символы "MonTueWedThuFriSatSun", a MONNAMES содержит символы "JanFebMarAprMayJunJulAugSepOctNovDec". С помощью этих массивов вы можете получить название дня недели/месяца по его порядковому номеру.

Примеры:

\ выводим на консоль название 1-го месяца
1 1- 3 * MONNAMES COUNT DROP + 3 TYPE CR
\ выводим на консоль название 12-го месяца
12 1- 3 * MONNAMES COUNT DROP + 3 TYPE CR
\ выводим на консоль название 3-го дня недели
3 1- 3 * WDAYS COUNT DROP + 3 TYPE CR
\ выводим на консоль название 5-го дня недели
5 1- 3 * WDAYS COUNT DROP + 3 TYPE CR 

SD.M.Y>Day ( addr u -- days )

Кладет на стек количество дней, прошедших от начала летоисчисления по григорианскому календарю до указанной даты. В качестве аргумента принимает строку с датой в формате DD.MM.YYYY.

Пример:

\ выводим на консоль количество дней,
\ прошедших до 31.12.2002
S" 31.12.2002" SD.M.Y>Day . CR

SDD.MM.YYYY ( addr u -- y m d )

Конвертирует строку в формате DD.MM.YYYY в дату (формат YMD).

Пример:

\ конвертируем строку "31.12.2002" в три числа (YMD)
\ и выводим эти числа на консоль
S" 31.12.2002" SDD.MM.YYYY . . . CR

SH:M>Min

Принимает в качестве аргумента строку со временем в формате HH:MM и конвертирует это время в число, содержащее количество минут.

Примеры:

\ переводим строки "1:20" и "01:20" 
\ в количество минут (80)
S" 1:20" SH:M>Min . CR
S" 01:20" SH:M>Min . CR

START-TIME?

Проверяет, совпадает ли текущее время с началом первой минуты после старта nnCron. Возвращает TRUE (-1), если это соответствует действительности и FALSE (0) в противном случае. Слово START-TIME? удобно использовать, например, для предотвращения запуска задачи при старте nnCron.

Пример:

#( test_nostartup
\ запускаться каждую минуту, но не в начале
\ первой минуты после старта nnCron
Rule: START-TIME? 0=
Action:
    \ ...
)#

TASK-CREATION-TIME ( -- d t= | -- f=)
TASK-EXECUTION-TIME ( -- d t= | -- f=)

При использовании внутри задачи, эти слова позволяют получить доступ к информации о времени создания текущей задачи (вернее времени последнего изменения хотя бы одной из конструкций Time: этой задачи) и времени последнего выполнения текущей задачи..

Слово TASK-CREATION-TIME возвращает флаг TRUE и время создания задачи либо просто флаг FALSE, если программе не удается вычислить время. Слово TASK-EXECUTION-TIME возвращает флаг TRUE и время последнего выполнения текущей задачи или флаг FALSE, если программе не удается вычислить время.

Оба слова возвращает время в формате FILETIME.

Примеры:

#( test_task_time 
\ каждые две минуты выводим на консоль 
\ время создания текущей задачи
Time: */2
Action:
    TASK-CREATION-TIME 
    IF
        FT>DD.MM.YYYY/hh:mm:ss TYPE CR 
    THEN
)#

#( test_task_time1
\ создаем специальные слова и каждые три минуты 
\ выводим на консоль время создания и выполнения 
\ текущей задачи
: FT. FT>DD.MM.YYYY/hh:mm:ss TYPE ;
: ?FT. IF FT. ELSE ." none" THEN ;
Time: */3
Action:
   TASK-CREATION-TIME ?FT. CR
   TASK-EXECUTION-TIME ?FT. CR
)#

TimeMin@ ( -- CurrentTime_in_minutes )
TimeSec@ ( -- CurrentTime_in_seconds )

Кладет на стек текущее время в минутах/секундах (количество минут/секунд, прошедших с ближайшей полуночи).

Примеры:

\ выводим на консоль текущее время в минутах/секундах
TimeMin@ . CR
TimeSec@ . CR

WEEK-DAY ( y m d -- wd[1-7] )

Кладет на стек порядковый номер дня недели (1 ... 7), на который попадает указанная дата в формате YMD.

Пример:

\ выводим на консоль день недели,
\ на который попадает 31 декабря 2002
2002 12 31 WEEK-DAY . CR

См. также: