Добрый день подскажите как правильно реализовать задачу?
Есть переменная с датой, нужно что бы когда текущая дата приблизится к переменной на 2 месяца загоралась авария (переменная аварии переходила в 1)
вот скрипт:
begin
{ если между текущим временем и vrCheckDate осталось меньше 2 месяцев }
if MonthsBetween(Now, data_poverki_1_1.AsDateTime) < 2 then
bahilova4_alarm_poverki_1.Value := 1
else
bahilova4_alarm_poverki_1.Value := 0;
end.
Проблема в том что он работает правильно и выполняет мои требования но когда проходит 2 месяца после указанной переменной авария пропадает, а мне нужно чтобы авария сохранялась постоянно, пока переменная не поменяется!
и второй вопрос этот скрипт можно использовать только для одной переменной , для другой нужно изменять название переменных.. и так постоянно, это очень неудобно так как их очень много! возможно ли сделать какой нибудь универсальный чтобы использовать для всех?
vyacheslav!
Судя по описанию, значение функции MonthsBetween это интервал между двумя значениями дат, т.е всегда неотрицательно.
Можно сравнивать заданную и текущую дату воспользовавшись определением типа TDateTime в Delphi и сравнивая "по дням":
begin
bahilova4_alarm_poverki_1.Visible := (NOW() + 60) >= data_poverki_1_1.AsDateTime;
end.
Сравнение по дням более логично, чем сравнение по месяцам.
Пример во вложении.
Здравствуйте.
но когда проходит 2 месяца после указанной переменной авария пропадает
Как выше отметил pan2000, функция MonthsBetween всегда возвращает положительное значение, поэтому в ваше условие нужно добавить проверку
var
myDate: TDateTime;
begin
myDate := data_poverki_1_1.AsDateTime;
{ если между текущим временем и vrCheckDate осталось меньше 2 месяцев }
if (Now > myDate) and (MonthsBetween(Now, myDate) < 2) then
bahilova4_alarm_poverki_1.Value := 1
else
bahilova4_alarm_poverki_1.Value := 0;
end.
возможно ли сделать какой нибудь универсальный чтобы использовать для всех?
У Вас переменная даты/времени "data_poverki_1_1" привязана к какому-либо объекту? Допустим она привязана к объекту Календарь (https://simple-scada.com/help/manual/calendar.html) в качестве основной переменной. Тогда назначаем этому же календарю переменную "bahilova4_alarm_poverki_1" в качестве дополнительной (см. скрин во вложении) в меню скриптов создаём новый универсальный скрипт со следующим кодом:
var
aObject: TM_Object;
myDate: TDateTime;
begin
{ прерываем скрипт, если он вызван не объектом }
if not (Sender is TM_Object) then Exit;
aObject := Sender as TM_Object;
{ дату/время берём из основной переменной объекта }
myDate := aObject.AsDateTime;
{ меняем доп. переменную в зависимости от условия }
if (Now > myDate) and (MonthsBetween(Now, myDate) < 2) then
aObject.VariableEx.Value := 1
else
aObject.VariableEx.Value := 0;
end.
Теперь этот скрипт привязываем к событию OnDataChange календаря. Далее можно создать сколько угодно объектов, назначить им основную и дополнительную переменную и привязать данный универсальный скрипт на событие OnDataChange. Напишите если что-то непонятно.
А по моему условию перемененная bahilova4_alarm_poverki_1 должно становиться 1, когда значение переменной data_poverki_1_1 становиться меньше текущей на 2 месяца и держит ее постоянно в 1, пока я не поменяю значение переменной в дату которая больше текущей минимум на 2 месяца.
Тогда нужно брать условия из кода Вашего первого сообщения, без изменений и использовать их:
var
aObject: TM_Object;
myDate: TDateTime;
begin
{ прерываем скрипт, если он вызван не объектом }
if not (Sender is TM_Object) then Exit;
aObject := Sender as TM_Object;
{ дату/время берём из основной переменной объекта }
myDate := aObject.AsDateTime;
{ меняем доп. переменную в зависимости от условия }
if (MonthsBetween(Now, myDate) < 2) then
aObject.VariableEx.Value := 1
else
aObject.VariableEx.Value := 0;
end.
Учитывайте также, что данный универсальный скрипт ставится на событие OnDataChange и будет срабатывать только при изменении переменной даты (data_poverki_1_1). Соответственно переменная аварии (bahilova4_alarm_poverki_1) будет меняться только в эти моменты.
то есть я правильно понял если переменная bahilova4_alarm_poverki_1 перевелась в 1, то ей и останется пока переменная data_poverki_1_1 не поменяется. в не зависимости от тога прошло 2 и более месяца с даты (data_poverki_1_1).?
Да, т.е. весь скрипт и его проверки будут выполнены только при изменении переменной даты data_poverki_1_1.
Этот код:
if (MonthsBetween(Now, myDate) < 2) then
aObject.VariableEx.Value := 1
else
aObject.VariableEx.Value := 0;
работает очень примитивно. Он записывает 1 в переменную аварии всегда, когда переменная даты приблизилась к текущей дате менее чем на 2 месяца (с любой стороны, с будущего, либо с прошедшего времени) и 0 во всех иных случаях.
но проблема в том если вносишь дату переменной data_poverki_1_1 сразу ниже текущей на 2 месяца (это аварийное событие) то она не переводит bahilova4_alarm_poverki_1 в еденицу (не считает ее аварией)
Верно, потому что в Вашем коде, приведённом выше, в переменную аварии запишется 0, если переменная даты ушла от текущей даты на 2 и более месяца. Чтобы было наоборот, можно изменить знак в условии:
if (MonthsBetween(Now, myDate) >= 2) then
aObject.VariableEx.Value := 1
else
aObject.VariableEx.Value := 0;
за исключением того что через два месяца после даты , авария снимается
Просто добавьте нужное Вам условие перед снятием аварии, чтобы авария не снималась:
if (MonthsBetween(Now, myDate) < 2) then
aObject.VariableEx.Value := 1
else
{ снимаем аварию только если заданная дата находится "до" текущей даты }
if (myDate < Now) then
aObject.VariableEx.Value := 0;
В этом варианте переменная аварии не будет сниматься если значение даты больше (т.е. стоит после) текущей даты (не важно на сколько месяцев).
Конструкции из вложенных if:
if (MonthsBetween(Now, myDate) < 2) then
aObject.VariableEx.Value := 1
else
{ снимаем аварию только если заданная дата находится "до" текущей даты }
if (myDate > Now) then
aObject.VariableEx.Value := 0;
определяет значение переменной aObject.VariableEx.Value следующим образом:
относительное значение Now - myDate | -2 0 +2
-----------------------------------------------------------------------------------> время (месяцев)
(MonthsBetween(NOW, myDate) < 2) | false | true | false
-----------------------------------------------------------------------------------------------
(myDate > Now) | true | х | false
-----------------------------------------------------------------------------------------------
aObject.VariableEx.Value | 0 | 1 | сохраняет значение
-----------------------------------------------------------------------------------------------
Значение переменной aObject.VariableEx.Value в случае "когда проходит 2 месяца после указанной переменной" (NOW - myDate) > 2
определено предисторией, т.е. при перезапуске проекта в этом временном интервале пременная будет инициализирована 0.
Доопределить значение переменной для всего временого интервала можно добавив альтернативу else с присвоением переменной 1 или
объеденив два условия:
if (MonthsBetween(Now, myDate) < 2) or (myDate < Now) then // интервал между датами < 2 месяцев ИЛИ дата поверки уже прошла
aObject.VariableEx.Value := 1
else
aObject.VariableEx.Value := 0;