И так код функционального блока на ST для извлечения "Год, Месяц, День месяца, Номер дня недели, Час, Минута, Секунда"
Для чего я "изобрел велосипед" если в библиотеке МАКРОСОВ уже есть готовый пример?

Для программистов объяснение простое - инкапсуляция.
Для электриков (и тех кто развился в КИС-овца из Школы Профессиональных Электриков) скажу так: специалист по эксплуатации ЩИТ-а не лезет внутрь. Для него разработчиком ЩИТ-а предусмотрены Лампы сигнализации, Переключатели управления на лицевой панели. Так же и для программиста - "спрятать" от пользователя устройство "внутренней кухни" - это не из разряда "красоты", а необходимый практический прием для системы, эксплуатируемой и поддерживаемый годами
Для эстетов визуального программирования ( а я общался на этом форуме с несколькими Профессионалами - без сарказма) обья]снение такое - по мне если приходится "протаскивать" сервисные переменные часов к каждому Блоку (макросу, ФБ), то это "захламляет полотно", прячет красоту логической мысли ... а тех для тех кто будет это в дальнейшем эксплуатировать ... вообщем может не получить эстетического удовольствия .

Код функционального блока привожу как есть. В нем скорее всего есть ошибки, которые я не нашел
Но в будущем, если сам найду, то поправлю здесь .... собственно как написал выше - выкладываю в первую очередь для себя же

///<Description>Возвращает год, месяц, день, день недели, час, минуту, секунду на основании значения системной функции get_date_time(). В ОТКЛюченном состоянии все выходы равны 0. Может быть использовано в программном коде на ST.</Description>
///<GroupName>Дата и время</GroupName>

(*

ПРИМЕР ИСПОЛЬЗОВАНИЯ в коде на ST.

function_block NameOfMyFB
var //объявление локальных переменных
....
varDateTime : USR.getDateTime; //тип переменной - имя функционального блока
...
y,m,d,dw,h,m,s :udint; // переменные год, месяц, день, номер дня недели, час, минусат, секунда
...
end_var

....
// создаем экземпляр функционального блока, передаем значение на Вход, получаем значение Выходов (значение Выходов будет записано в указанные локальные переменные)
varDateTime (ENABLE := true, Year => y, Month => m, Day => d, DayOfWeek => dw, Hour => h, Minute => m, Second => s);

// Логика использования значений: год, месяц, день, номер дня недели, час, минута, секунда
....

end_function_block


ОСОБЕННОСТИ РЕАЛИЗАЦИИ
1. Функциональный блок может быть использован в управляющей программе прибора, который оснащен источником часов реального времени (доступны системные функции часов реального времени).
2. "Год, месяц, день" вычисляется в первом цикле управляющей программы (после создания экземпляра функционального блока) и далее, пере-вычисляется, в одном цикле управляющей программы, в котором произошла смена суток.
Из этой реализации есть два следствия:
а) "Длинные" циклы вычисления "Год, Месяц, День" выполняются только тогда, когда они необходимы. В остальных случаях "Год, Месяц, День" восстанавливается из локальной памяти экземпляра функционального блока.
б) при каждом ОТКЛ/ВКЛ на входе ENABLE происходит пересчет "Год, Месяц, День". Рекомендуется оценивать целесообразность изменения значения входа ENABLE в коде управляющей программы.

3. Функциональный блок используется значения, возвращаемые системными функциями get_date_time() и SYS.is_leap_year() для версии OL: 2.7.354.0.
При изменениях Производителем протокола работы этих системных функций требуется проверка (тестирование) кода функционального блока.

ОТКАЗ ОТ ГАРАНТИЙ
Права копирования, воспроизведения, передачи функционального блока, полностью и/или частично, реулируется лицензионным соглашением Производителя OL.
Код функцинального блока не использует другие лицензируемые библиотеки.
Код функционального блока приведен как есть, рекомендован к ознакомлению исключительно в образовательных целях.
Использование лицом функционального блока, полностью и/или частично, в проектах означает принятие этим лицом всех рисков убытков и/или любых других последствий.
С момента первого, полностью и/или частично, копирования и/или воспроизведения функционального блока вы соглашаетесь со всеми вышеперечисленными условиями отказа от гарантий (безусловный акцепт оферты).
*)

function_block USR.getDateTime //имя функционального блока.
var_input //объявление входных переменных
///<Description>ВКЛючить / ОТКЛючить работу функционального блока. В ОТКЛюченном состоянии все выходы равны 0. Допустимые значения: TRUE - ВКЛючен FALSE - ОТКЛючен. </Description>
ENABLE : bool;
end_var

var_output //объявление выходных переменных
///<Description>Год системных часов реального времени. Диапазон выходных значений: 0 - ФБ ОТКЛючен, 2000 .. 2136</Description>
Year : udint;
///<Description>Минута системных часов реального времени. Диапазон выходных значений: 0 - ФБ ОТКЛючен, 1 .. 12</Description>
Month : udint;
///<Description>Секунда системных часов реального времени. Диапазон выходных значений: 0 - ФБ ОТКЛючен, 1 .. 31</Description>
Day : udint;
///<Description>Номер Дня недели системных часов реального времени. Диапазон выходных значений: 0 - ФБ ОТКЛючен, 1 - ПН .. 7 - ВС</Description>
DayOfWeek: udint;
///<Description>Час системных часов реального времени. Диапазон выходных значений: 0 .. 23</Description>
Hour : udint;
///<Description>Минута системных часов реального времени. Диапазон выходных значений: 0 .. 59</Description>
Minute : udint;
///<Description>Секунда системных часов реального времени. Диапазон выходных значений: 0 .. 59</Description>
Second : udint;
end_var

var //объявление локальных переменных
ucSecondPerDay : udint := 86400; // константа, число секунд в сутках
ucSecondPerHour : udint := 3600; // константа, число секунд в часе
ucSecondPerMinute : udint := 60; // константа, число секунд в минуте
ucDaysPerWeek : udint := 7; // константа, число дней в неделе
ucSYSYear : udint := 2000; // константа, год для нулевого значения регистра секунд, возвращаемого системной функцией get_date_time() / 01.01.2000
ucSYSWeekDay : udint := 6; // константа, номер дня недели для нулевого значения регистра секунд, возвращаемого системной функцией get_date_time() / 01.01.2000 / Суббота
uLastYear : udint := 0; // переменная используется для хранения года
uLastMonth : udint := 0; // переменная используется для хранения месяца
uLastDay : udint := 0; // переменная используется для хранения дня
uLastDayOfWeek : udint := 0; // переменная используется для хранения номера для недели
uLastDateTime : udint := 0; // переменная используется для хранения предыдущего значения возвращаемого системной функцией get_date_time()
uaDayInMonths: ARRAY [0..11] OF UDINT; // масив констант, количество дней в месяце
end_var

// обнуление выходов и завершение исполнения, если вычисления не требуются
if not ENABLE then
Year := 0;
Month := 0;
Day := 0;
DayOfWeek := 0;
Hour := 0;
Minute := 0;
Second := 0;
RETURN;
end_if

// Присваиваем значения массиву констант: число дней в каждом месяце года
if 0 = uLastDayOfWeek then // инициализируем масив "один раз", в первом рабочем цикле после создания экземпляра функционального блока
uaDayInMonths[0] := 31; // число дней в месяце, ЯНВАРЬ
uaDayInMonths[1] := 28; // число дней в месяце, ФЕВРАЛЬ, в високосном году - 29.
uaDayInMonths[2] := 31; // число дней в месяце, МАРТ
uaDayInMonths[3] := 30; // число дней в месяце, АПРЕЛЬ
uaDayInMonths[4] := 31; // число дней в месяце, МАЙ
uaDayInMonths[5] := 30; // число дней в месяце, ИЮНЬ
uaDayInMonths[6] := 31; // число дней в месяце, ИЮЛЬ
uaDayInMonths[7] := 31; // число дней в месяце, АВГУСТ
uaDayInMonths[8] := 30; // число дней в месяце, СЕНТЯБРЬ
uaDayInMonths[9] := 31; // число дней в месяце, ОКТЯБРЬ
uaDayInMonths[10] := 30; // число дней в месяце, НОЯБРЬ
uaDayInMonths[11] := 31; // число дней в месяце, ДЕКАБРЬ
end_if

// Восстанавливаем значения год, месяц, день из локальной памяти экземпляра функцинального блока.
Year := uLastYear;
Month := uLastMonth;
Day := uLastDay;

// конвертируем значения get_date_time() в Номер Дня недели.
DayOfWeek := ( (dt_to_udint(get_date_time()) / ucSecondPerDay) + ucSYSWeekDay) mod ucDaysPerWeek; // високосный год не влияет на последовательность номеров дней в неделе
// переводим со шкалы: 0=ВС ... 6=СБ на шкалу: 1=ПН ... 7=ВС
if DayOfWeek = 0 then DayOfWeek := 7; end_if

// конвертируем значения get_date_time() в Час, Минута, Секунда
Hour := ( dt_to_udint(get_date_time()) mod ucSecondPerDay ) / ucSecondPerHour; //Час системых часов реального времени
Minute := ( (dt_to_udint(get_date_time()) mod ucSecondPerDay ) mod ucSecondPerHour ) / ucSecondPerMinute; //Минута системых часов реального времени
Second := ( (dt_to_udint(get_date_time()) mod ucSecondPerDay ) mod ucSecondPerHour ) mod ucSecondPerMinute; //Секунда системых часов реального времени

(*
Системная Дата и/или Время может быть изменена в системном меню прибора, по сетевому протоколу и ... при отладке в OL.
В случае измения системной Даты и/или Времени при котором не произошло изменение номера Дня недели, необходимо пересчитать Год, Месяц, День.
В локальной переменной uLastDateTime храним значение get_date_time() на предыдущем рабочем цикле управляющей программы.
Если разница между значением get_date_time() на предыдущем цикле больше 1 секунды значения get_date_time() на текущем цикле, то устанавливаем признак "Пересчитать Год, Месяц, День"
В качестве признака "Пересчитать Год, Месяц, День" используем значение переменной uLastDayOfWeek
*)
if abs(udint_to_real((dt_to_udint(get_date_time()) - uLastDateTime))) > 1.0 then uLastDayOfWeek := 0; end_if;
// uLastDateTime сохраняем значение get_date_time() для следующего рабочего цикла управляющей программы.
uLastDateTime := dt_to_udint(get_date_time());

(*
Вычисление "Год, Месяц, День" требует выполнения "длинной" цепочки арифмитических вычислений.
Значение "Год, Месяц, День" изменяется одн раз в сутки.
Целесообразно выполнять код вычисления "Год, Месяц, День" в случае если изменились Сутки.
Используем переменную uLastDayOfWeek в качестве признака "Пересчитать Год, Месяц, День".
Если не требуется выполнить пересчет "Год, Месяц, День", то выходим из ФБ.
*)
if uLastDayOfWeek = DayOfWeek then RETURN; end_if;

// Начинаем вычисление "Год, Месяц, День"
// uLastDayOfWeek сохраняем значение Номера Дня недели для следующего рабочего цикла управляющей программы.
uLastDayOfWeek := DayOfWeek;

// вычисляем текущий год. До 25 вычислений на 1 цикл управляющей программы для 2025 года. 30 для 2030 ... 136 для 2136 года (2136 - это предел регистра секунд системной функции get_date_time()).
Year := ucSYSYear; // начинаем с нулевой точки отсчета и далее вычитаем дни, пока не дойдем до текущего года
Day := dt_to_udint(get_date_time()) / ucSecondPerDay;
WHILE true DO
IF SYS.is_leap_year(Year) THEN
if Day > 366 then
Day := Day - 366;
Year := Year + 1;
else EXIT; end_if;
ELSE
if Day > 365 then
Day := Day - 365;
Year := Year + 1;
else EXIT; end_if;
END_IF;
END_WHILE;

// вычисляем месяц. До 12 вычислений на 1 цикл управляющей программы
Month := 0; // начинаем с января и далее вычитаем дни, пока не дойдем до текущего месяца
WHILE true DO
IF not SYS.is_leap_year(Year) THEN
if Day > (uaDayInMonths[Month]) then
Day := Day - uaDayInMonths[Month];
Month := Month + 1;
else EXIT; end_if;
ELSE
if Month = 1 then // февраль високосного года
if Day > (uaDayInMonths[Month] + 1) then
Day := Day - uaDayInMonths[Month] - 1; // в феврале високосного года 29 дней
Month := Month + 1;
else EXIT; end_if;
else
if Day > (uaDayInMonths[Month]) then
Day := Day - uaDayInMonths[Month];
Month := Month + 1;
else EXIT; end_if;
end_if;
END_IF;
END_WHILE;

// Корректируем результаты вычисления месяца и дня
Month := 1 + Month;
Day := 1 + Day;

// Сохраняем вычисленные значения в локальной памяти экземпляра функцинального блока.
// Вычисленные в этом цикле значения будут пере-использованы в следующих циклах управляющей программы.
uLastYear := Year;
uLastMonth := Month;
uLastDay := Day;

end_function_block