Все-таки, Алиса была права, на пограничных датах могут быть проблемы. Я гонял, гонял, у меня все нормально было, вы же нашли. Так что, если не хотим внешними функциями пользоваться, то тогда перебором
Вид для печати
Ну да, вот универсальный код (за исключением первой строчки)
Код:// <Description>Извлечение даты и времени из формата UnixTime от 01.01.2000</Description>
/// <GroupName>Дата и время</GroupName>
function_block UDT_to_DateTime // от 01.01.2000
var_input
UDT: udint := 0; //дата и время в формате Unix от 01.01.2000 в секундах (если = 0, то берем системное время)
end_var
var_output
day: udint;
month: udint;
year: udint;
hour: udint;
min: udint;
sec: udint;
week: udint;
end_var
var
day_month: array [1..12] of udint := [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
uiDate, uiDay: udint;
days_to_year, days_to_month: udint;
is_leap_year: bool;
end_var
if UDT = 0 then UDT := dt_to_udint(get_date_time()); end_if;
//Общее количество дней
uiDate := UDT / 86400;
//Приблизительно определяем год
Year := uiDate / 365 + 2000;
//Количество дней от 01.01.2000 до начала года
days_to_year := (Year - 2000)*365 + (Year - 1997)/4 - (Year - 1901)/100 + (Year-1601)/400;
//Уточняем год
if uiDate < days_to_year then
Year := Year - 1;
days_to_year := (Year - 2000)*365 + (Year - 1997)/4 - (Year - 1901)/100 + (Year-1601)/400;
end_if
//Количество дней от начала года
uiDay := uiDate - days_to_year + 1;
//Приблизительно определяем месяц
month := uiDay / 29 + 1;
if month > 12 then month := 12; end_if
//Проверяем год на високосность
is_leap_year := (Year mod 400 = 0) or ((Year mod 4 = 0) and (Year mod 100 <> 0));
//Количество дней от нового года до начала месяца
days_to_month := day_month[month] + bool_to_udint(is_leap_year and Month > 2);
//Уточняем месяц
if uiDay <= days_to_month then
Month := Month - 1;
days_to_month := day_month[month] + bool_to_udint(is_leap_year and Month > 2);
end_if
//Находим день
Day := uiDay - days_to_month;
//Время
hour := (UDT / 3600) mod 24;
min := (UDT / 60) mod 60;
sec := UDT mod 60;
//День недели
week := ((UDT / 86400 + 6) mod 7);
if week = 0 then week := 7; end_if
end_function_block
Кстати, не понял, а почему мы так делаем
проще же можноКод:week := ((UDT / 86400 + 6) mod 7);
if week = 0 then week := 7; end_if
И, еще,Код:week := ((UDT / 86400 + 5) mod 7) + 1;
нагляднее будетКод:year := uiDate / 365 + 2000;
days_to_year := (year - 2000)*365 + (year - 1997)/4 - (year - 1901)/100 + (year-1601)/400;
и только в конце уже добавить 2000Код:year := uiDate / 365; //Приблизительно определяем год
days_to_year := year * 365 + (year + 3)/4 - (year + 99)/100 + (year + 399)/400;
С Днём недели можно, а с годами можно так
Последний вариант универсального ФБ времени, версия 5, выложил тут https://owen.ru/forum/showthread.php...l=1#post444236Код:
year := uiDate / 365; //Приблизительно определяем год
days_to_year := year * 365 + (year + 3)/4 - (year + 99)/100 + (year + 399)/400;
if uiDate < days_to_year then
Year := Year - 1 ;
days_to_year := year * 365 + (year + 3)/4 - (year + 99)/100 + (year + 399)/400;
end_if
year := year+2000;