Не получается доверять ИИ пока…. ИИ.. ИИ. искусственный интеллект.. ИИ. искусственный интеллект. оптимальность решения.. ИИ. искусственный интеллект. оптимальность решения. Программирование.. ИИ. искусственный интеллект. оптимальность решения. Программирование. разработка.

Хотел сделать это как пост, но символов не хватило…

Пишу на RPG под IBM i. И вот возникла проблема на вход некоей функции приходит дата в виде строки в формате ISO (YYYY-MM-DD). Ее надо проверить на корректность и перевести в формат CYMD (CYYMMDD где C – век, 0 для 1900Б 1 для 2000 и т.п.) в число zoned(7) (формат с фиксированной точкой, 7 знаков). Да, формат экзотический, но на IBM i используется, поддерживается и достался нам в наследство от разработчиков нашей АБС – компании MySys.

Проблема в том, что у форматов ISO и CYMD разные допустимые диапазоны дат – 01 JAN 0001 – 31 DEC 9999 для ISO и 01 JAN 1900 – 31 DEC 2899 для CYMD (первый символ – век – может меняться только в диапазоне от 0 для 20-го верка до 9 для 29-го).

Т.е. даже провалидировал входящую строку на предмет того что там содержится корректная ISO дата, нет уверенность что при конвертации в CYMD не случится исключения по причине того, что эта дата выходит за границы диапазона CYMD.

Естественно, я знаю как это правильно и эффективно сделать. Но решил проверить ИИшку. Сформулировал задачу, запустил. Получил ответ

dcl-s inputDate  char(10);         // Входная строка 'YYYY-MM-DD'
dcl-s validDate  date(*iso);       // Переменная для проверки
dcl-s resultCymd zoned(7:0);       // Результат в Zoned

dcl-s minCymd    date(*iso) inz(D'1900-01-01');
dcl-s maxCymd    date(*iso) inz(D'2899-12-31');

inputDate = '2026-09-10'; // Тестовое значение

monitor;
  // 1. Проверка на валидность *ISO
  // Если строка не является датой, %date вызовет исключение
  validDate = %date(inputDate : *iso);

  // 2. Проверка на попадание в диапазон *CYMD (1900-2899)
  if (validDate >= minCymd) and (validDate <= maxCymd);

    // Конвертация в строку формата *CYMD0 (без разделителей: CYYMMDD)
    // и последующий перевод в zoned(7:0)
    resultCymd = %dec(%char(validDate : *CYMD0) : 7 : 0);

    dsply ('Converted: ' + %char(resultCymd));
  else;
    dsply 'Date out of CYMD range';
  endif;

on-error *date_err;
  dsply 'Invalid ISO date format';
endmon;

В целом, решение верное, но не самое эффективное и громоздкое. Задаю наводящий вопрос – а не проще будет вот так:

test(de) *iso inputDate;

if not %error;
  validDate = %date(inputDate : *iso);
  if validDate in %range(minCymd: maxCymd);
    resultCymd = %dec(validDate: *cymd);
  endif;
endif;

И вот тут ее понесло…

1. test(de) — это не функция RPGLE Команда test(de) не существует в языке RPGLE. Вероятно, вы имели в виду логику из других языков или старых спецификаций, но в Free-form RPGLE для проверки корректности данных используется только блок monitor или проверка %error после операции, которая может вызвать исключение.

2. %error не работает сама по себе Переменная %error не является глобальным флагом, который можно проверить через if not %error. %error используется только внутри блока monitor в секции on-error, чтобы определить, какая именно ошибка произошла. Если вы вызовете %date() с некорректной строкой вне блока monitor, программа просто завершится с дампом (Runtime Error), и до вашего if дело даже не дойдет.

3. %dec(validDate : cymd) — так нельзя Функция %dec() принимает либо строку, либо число. Она не принимает тип DATE и не поддерживает указание формата даты (например, cymd) в качестве второго аргумента. Чтобы получить числовое представление даты в формате CYMD, нужно обязательно пройти через промежуточное преобразование в строку: %dec(%char(dateVar : CYMD0) : 7 : 0)

4. %range Функция %range не является встроенной функцией RPGLE. Для проверки диапазона используется стандартное сравнение: (date >= min) and (date <= max).

Здравствуете, я ваша тетя… Есть официальная документация от IBM, там все это расписано.

Пришлось повозить носом по столу

  1. test(de) является допустимой операцией RPGLE

  2. BIF %dec в RPGLE, если аргументом является дата, допускает использовать вторым аргументов формат

  3. %range является BIF в современной версии RPGLE

Сразу включила заднюю

Приношу извинения за неточность в предыдущем ответе. Вы правы: в последних версиях IBM i (особенно в самых актуальных релизах TR) были расширены возможности BIF и добавлены новые операторы. Если ваша версия ОС и компилятора поддерживает эти функции, то ваш подход действительно становится самым оптимальным и лаконичным. Разбор вашего варианта с учетом уточнений:

  • test(de): Эта операция позволяет проверить, может ли строка быть преобразована в дату, не вызывая при этом исключения (Runtime Error). Это значительно чище, чем использование monitor.

  • %range: Современная BIF, которая заменяет громоздкую конструкцию (x >= min) and (x <= max).

  • %dec(date : *cymd): Прямое преобразование даты в число с указанием формата — это максимально эффективный способ, исключающий лишний шаг с %char.

В итоге выдала примерно то, что я бы написал сам, но быстрее

dcl-s inputDate  char(10) inz('2026-09-10');
dcl-s validDate  date(*iso);
dcl-s resultCymd zoned(7:0);

dcl-s minCymd    date(*iso) inz(D'1900-01-01');
dcl-s maxCymd    date(*iso) inz(D'2899-12-31');

// 1. Проверка валидности формата *ISO
test(de) *iso inputDate;

if not %error;
  validDate = %date(inputDate : *iso);

  // 2. Проверка диапазона и конвертация
  if validDate in %range(minCymd : maxCymd);
    resultCymd = %dec(validDate : *cymd);
  endif;
endif;

Еще и резюмировала

Почему этот вариант лучше:

  • Производительность: Нет накладных расходов на механизм обработки исключений (monitor).

  • Читаемость: Код читается почти как естественный язык.

  • Компактность: Минимум строк при сохранении полной безопасности проверки.

До мелочей (что граничные значения лучше задавать константами) уж не стал докапываться

  dcl-s inputDate  char(10) inz('0026-09-10');
  dcl-s validDate  date(*iso);
  dcl-s resultCymd zoned(7:0);

  dcl-c minCymd    const(D'1900-01-01');
  dcl-c maxCymd    const(D'2899-12-31');

  // 1. Проверка валидности формата *ISO
  test(de) *iso inputDate;

  if not %error;
    validDate = %date(inputDate : *iso);

    // 2. Проверка диапазона и конвертация
    if validDate in %range(minCymd : maxCymd);
      resultCymd = %dec(validDate : *cymd);
      dsply ('*CYMD date: ' + %editc(resultCymd: 'X'));
    else;
      dsply ('Date out of *CYMD range');
    endif;
  else;
    dsply ('Invalid *ISO date');
  endif;

Но правильно кто-то сказал –

ИИ хорошо делает то, в чем ты не разбираешься. А в чем разбираешься – делает плохо.

От нее можно добиться вменяемого результата, но для этого надо очень хорошо понимать какой это должен быть результат и на каждом этапе направлять ее на путь истинный. И времени на это может уйти больше, чем сделать самому сразу правильно.

Понятно, что есть скиллы и все такое… Но хочется готовый инструмент, а не “помощника”, которого нужно постоянно обучать, контролировать и подтирать за ним сопли и в итоге думать каждый раз – он действительно выдал хорошее решение, или опять его надо чему-то доучивать…

Хотя в ряде ситуаций оно, конечно, помогает. Если не требовать от нее слишком многого и не слишком ей доверять (примеров ошибочных или неполных суждений уже тоже накоплено).

Так что вряд ли нам пока грозит быть вытесненными с рынка разработки. Другое дело, что порог входа повысится – на уровне джуна бессловесного оно уже может что-то такое изобразить, может быть даже на уровне начинающего мидла… Но вот куда брать сеньоров, если джунов заменить на ИИ…

Автор: SpiderEkb

Источник