Страница 2 из 2 ПерваяПервая 12
Показано с 11 по 16 из 16

Тема: ФБ даты и время на ST

  1. #11
    Пользователь
    Регистрация
    09.12.2013
    Адрес
    Ставрополь
    Сообщений
    1,996

    По умолчанию

    Цитата Сообщение от kondor3000 Посмотреть сообщение
    Функция SYS.is_leap_year(); уже встроена в ОЛ. Можно ещё сократить )))
    И время с 8 утра, 31 декабря 2025 года показывает 0 день января 2026 года.
    Все-таки, Алиса была права, на пограничных датах могут быть проблемы. Я гонял, гонял, у меня все нормально было, вы же нашли. Так что, если не хотим внешними функциями пользоваться, то тогда перебором

  2. #12

    По умолчанию

    Цитата Сообщение от Dimensy Посмотреть сообщение
    Все-таки, Алиса была права, на пограничных датах могут быть проблемы. Я гонял, гонял, у меня все нормально было, вы же нашли. Так что, если не хотим внешними функциями пользоваться, то тогда перебором
    Просто сильно сократили, у меня получилось вычисление дня до начала года и дня до начала месяца, по 2 одинаковых строки, с разными условиями.
    Наступил на те же грабли. Пока у себя проверял, набрался опыта )
    Последний раз редактировалось kondor3000; 07.11.2025 в 20:36.

  3. #13
    Пользователь
    Регистрация
    09.12.2013
    Адрес
    Ставрополь
    Сообщений
    1,996

    По умолчанию

    Цитата Сообщение от kondor3000 Посмотреть сообщение
    Просто сильно сократили, у меня получилось вычисление дня до начала года и дня до начала месяца, по 2 одинаковых строки, с разными условиями.
    Наступил на те же грабли. Пока у себя проверял, набрался опыта )
    Ну да, вот универсальный код (за исключением первой строчки)
    Код:
    // <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

  4. #14

    По умолчанию

    Цитата Сообщение от Dimensy Посмотреть сообщение
    Ну да, вот универсальный код (за исключением первой строчки)
    Почти один в один, как у меня)

    Скрытый текст:
    Код:
    /// <Description>Извлечение  времени и даты из UnixTime c 2000 г. </Description>
    /// <GroupName>ФБ Даты и времени</GroupName>
    function_block DT_UTC   // Извлечение  времени и даты из UnixTime
        var_input //объявление входных переменных
           DT_: udint;    // время  DT 
        end_var
        var_output //объявление выходных переменных    
           Has: udint;    //  Часы  
           Myn: udint;    //  Минуты
           Sek: udint;    //  Секунды       
           Day:udint;     //  День
           Month:udint;  //  MONTH  Месяц
           Year:udint;    // YEAR   Год
           D_Week:udint;  //  День недели
           DT1: udint;    // время  DT        
        end_var     
        var 
         DayInMonth: 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;  
         Timer: udint;  //  Время
        end_var  
        
        if DT_=0 then       
           DT_:=dt_to_udint(get_date_time());     // Дата и время  DT   
        end_if    DT1:=DT_;
        Timer:=DT_ MOD 86400; //  Время
        D_Week := ((DT_ / 86400 + 6) mod  7);
        if D_Week=0 then D_Week:=7; end_if       //  День недели
          Has:=Timer/3600; Myn:=Timer mod 3600/60;  Sek:=Timer mod 60; // Время   часы, минуты, сек.
          uiDate := DT_/ 86400;
          Year := uiDate / 365 + 2000;                          //  Год +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 
        days_to_month := DayInMonth[Month] + bool_to_udint( SYS.is_leap_year(Year) and Month > 2);
        if uiDay <= days_to_month then
          Month := Month - 1;
          days_to_month :=DayInMonth[Month] + bool_to_udint( SYS.is_leap_year(Year) and Month > 2);
        end_if
         Day := uiDay - days_to_month;     
         
    end_function_block
    Последний раз редактировалось kondor3000; 07.11.2025 в 22:53.

  5. #15
    Пользователь
    Регистрация
    09.12.2013
    Адрес
    Ставрополь
    Сообщений
    1,996

    По умолчанию

    Кстати, не понял, а почему мы так делаем
    Код:
    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;
    нагляднее будет
    Код:
    year := uiDate / 365;   //Приблизительно определяем год        
    days_to_year := year * 365 + (year + 3)/4 - (year + 99)/100 + (year + 399)/400;
    и только в конце уже добавить 2000

  6. #16

    По умолчанию

    Цитата Сообщение от Dimensy Посмотреть сообщение
    Кстати, не понял, а почему мы так делаем
    С Днём недели можно, а с годами можно так
    Код:
     
          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;
    Последний вариант универсального ФБ времени, версия 5, выложил тут https://owen.ru/forum/showthread.php...l=1#post444236
    Последний раз редактировалось kondor3000; 09.11.2025 в 18:59.

Страница 2 из 2 ПерваяПервая 12

Похожие темы

  1. BCD преобразования даты-времени
    от -=Vovka=- в разделе Панели оператора (HMI)
    Ответов: 10
    Последнее сообщение: 11.12.2018, 14:29
  2. Установка даты - времени в СП 270
    от spec_yug в разделе Панели оператора (HMI)
    Ответов: 4
    Последнее сообщение: 10.07.2014, 08:50
  3. к петрову и. (про время и даты ...)
    от Валенок в разделе ПЛК1хх
    Ответов: 27
    Последнее сообщение: 17.11.2011, 13:52
  4. Разбор даты
    от VanoKing в разделе Master SCADA 3
    Ответов: 7
    Последнее сообщение: 06.09.2011, 10:08
  5. установка времени и даты на плк
    от michaeladm в разделе ПЛК1хх
    Ответов: 2
    Последнее сообщение: 27.05.2010, 10:30

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •