сравнение даты и времени в предложении if - PullRequest
0 голосов
/ 28 мая 2018

У меня есть следующий код:

%if "&min_date"dt <= "02DEC2014:00:00:00"dt %then %do;
  /* some code */
%end

И он не ведет себя так, как я ожидаю.

Мой min_date уступает, но проверенное выражение оценивается как 0

%put &min_date; /* 31JAN1600:00:00:00 */
%put %eval("&min_date"dt <= "02DEC2014:00:00:00"dt); /* 0 */
%put %eval("31JAN1600:00:00:00"dt <= "02DEC2014:00:00:00"dt); /* 0 */

Как мне сделать эту работу?

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

Как вы показали,% EVAL не знает о литералах даты и времени, поэтому видит их как строковые значения.Поскольку% EVAL вызывается неявно с помощью оператора% IF.оператор% IF выполняет сравнение текста вместо сравнения чисел.

Хорошая новость:% SYSEVALF знает о литералах даты и времени:

%let min_date = 31JAN1600:00:00:00 ; 
%put %sysevalf("&min_date"dt) ;   /*-11357884800*/
%put %sysevalf("&min_date"dt <= "02DEC2014:00:00:00"dt);  /* 1 */
%put %sysevalf("31JAN1600:00:00:00"dt <= "02DEC2014:00:00:00"dt); /* 1 */

Вмакрос% IF:

%macro test(min_date=) ;
  %if %sysevalf("&min_date"dt <= "02DEC2014:00:00:00"dt) %then %do;
    %put &min_date is less than or equal to "02DEC2014:00:00:00"dt ;
  %end ;
  %else %do ;
    %put &min_date is NOT less than or equal to "02DEC2014:00:00:00"dt ;
  %end ;
%mend ;

, который возвращает журнал как:

124  %test(min_date=31JAN1600:00:00:00)
31JAN1600:00:00:00 is less than or equal to "02DEC2014:00:00:00"dt
125  %test(min_date=31JAN2015:00:00:00)
31JAN2015:00:00:00 is NOT less than or equal to "02DEC2014:00:00:00"dt
0 голосов
/ 29 мая 2018

На самом деле,% EVAL () сработал в вашем примере.:) Не так, как задумано, но вот почему:

  • Сначала% EVAL () проверяет, могут ли операнды оцениваться как арифметические (только целочисленные) или логические.

  • Поскольку вы предоставили 2 литерала даты-времени, которые содержали нецелые символы, было выполнено логическое сравнение на основе последовательности сортировки символов.

% SYSEVALF () - как упоминалось ранее - будет работать, потому что, в отличие от% EVAL (), он поддерживает нецелые символы в качестве операндов с дополнительной оценкой.

Так% SYSEVALF () поддерживает арифметику с плавающей запятой, тогда как% EVAL () может поддерживать только целые числа.

Кстати,% EVAL () также используется для вычисления выражений в% IFили оператор% DO и т. д., поэтому литералы даты и времени также не поддерживаются в этих случаях.

Примечание: учитывая вышесказанное, обычно рекомендуется:

  • для целого числаарифметика, используйте% EVAL ()
  • для арифметики с плавающей запятой, используйте% SYSEVAL ()
  • всегда преобразовывать литералы даты и времени в целое число, как в ответе выше, с% sysfunc (inputn (& datetimeliteral), datetimex.))

где x будет меняться в зависимости от литерала даты и времени ...

0 голосов
/ 28 мая 2018

Даже когда вы используете литералы, я думаю, что макросреда обрабатывает сравниваемые значения как строки - она ​​не пытается преобразовать литералы в базовые числовые значения перед выполнением сравнения.Если вы хотите, чтобы сравнение работало должным образом, вы должны преобразовать даты во что-то, что язык макрокоманды может сравнивать как число, например

%put %eval(%sysfunc(putn("&min_date"dt,16.)) <= %sysfunc(putn("02DEC2014:00:00:00"dt,16.)));

В качестве альтернативы, вы можете временно выйти из языка макросов итогда вы можете использовать литералы напрямую, например:

%put %eval(%sysfunc(intck(second,"&min_date"dt,"02DEC2014:00:00:00"dt)) > 0);
...