Да, сравнивает минимальную максимальную дату с датой сборки вместо текущей даты

#javascript #node.js #validation #momentjs #yup

#javascript #node.js #проверка #momentjs #ага

Вопрос:

Так что это довольно странно, и я не могу понять, откуда это берется.

У меня есть регистрация WS (в Node.js используя Sales.js ) если минимальный требуемый возраст равен 18 годам, проверка выполняется Yup.

Это моя схема yup:

 const yup = require('yup');
const moment = require('moment');

const birthdate = yup.date()
  .typeError('INVALID_DATE')
  .min(moment().subtract(115, 'years'), 'MIN_AGE')
  .max(moment().endOf('day').subtract(18, 'years'), 'MAX_AGE');

module.exports = {
  birthdate
};  

Как вы можете видеть из примера ниже, когда я указываю сегодняшнюю дату, она сравнивает ее с 2002-07-31 в то время как она должна сравниваться с moment().endOf('day').subtract(18, 'years') , которая была бы 2002-08-12

Обратите внимание, что 2002-07-31 это дата, в которую я создал проект. Так что, если я перекомпилирую его сейчас, у меня больше не будет этой проблемы на сегодняшний день. Если я завтра проведу повторное тестирование, оно сравнит его с сегодняшней датой! Я понятия не имею, как это возможно или как это исправить.

Это ошибка от yup:

 "errors": [{
  "field": "birthdate",
  "code": "E_MAX_AGE_BIRTHDATE",
  "params": {
    "path": "birthdate",
    "value": "2002-08-12T10:00:00.000Z",
    "originalValue": "2002-08-12T10:00:00.000Z",
    "max": "2002-07-31T21:59:59.999Z"
  }
}]  

Есть идеи?
Используемые версии: moment 2.24.0 ; yup 0.29.2

Ответ №1:

Для тех, кто хочет более простой способ получить динамическую дату (например, сейчас), которая вычисляется в момент проверки (например, не время на дату сборки): используйте yup.lazy().

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

 import { date, lazy, object, ref } from 'yup'

function getMinDate() {
    return new Date(2000, 1, 1)
}

function getMaxDate() {
    return new Date()
}

const schema = object({
    minDate: date()
        .min(getMinDate(), `Min start date is ${getMinDate()}`)
        .max(ref('maxDate'), 'Min date must be earlier than the max date'),
    maxDate: lazy(() => date()
        .min(ref('minDate'), 'Max date must be later than min date')
        .max(getMaxDate(), `Max start date is ${getMaxDate()}`)
  )
})  

Ответ №2:

Хорошо, я нашел решение.

На самом деле, Yup сохранит дату, которую вы изначально указали, и скомпилирует ее. Он больше не будет выполняться moment().endOf('day').subtract(18, 'years') каждый раз, когда вы подтверждаете дату.

Для этого вы должны использовать метод тестирования, а не min nor max .

Я создал метод расширения для yup.date следующим образом:

 /**
 * This function is used to format the error like date.min does
 */
function customValidationError(errorMessage, value, path, extraData) {
  const error = new yup.ValidationError(errorMessage,
    value,
    path);
  error.params = {
    path: path,
    value: value,
    originalValue: value,
    ...extraData
  };
  return error;
}

/**
 * Extension method to yup.date
 * You should pass a function that will be executed each time you want to check again the current date.
 * @name yup.dynamicMaxDate
 * @global yup.dynamicMaxDate
 */
yup.addMethod(yup.date, 'dynamicMaxDate', function(path, errorMessage = 'MAX_DATE', maxDateFunction) {
  return this.test(path, errorMessage,
    (value) => {
      const maxDate = maxDateFunction();
      return new Promise((resolve, reject) => {
        const error = customValidationError(errorMessage, value, path, {
          max: maxDate
        });
        value amp;amp; moment(value).isAfter(maxDate) ?
          reject(error) :
          resolve(true);
      });
    });
});

/**
 * Extension method to yup.date to check if date is before a given date
 * You should pass a function that will be executed each time you want to check again the current date.
 * @name yup.dynamicMinDate
 * @global yup.dynamicMinDate
 */
yup.addMethod(yup.date, 'dynamicMinDate', function(path, errorMessage = 'MIN_DATE', minDateFunction) {
  return this.test(path, errorMessage,
    (value) => {
      const minDate = minDateFunction();
      return new Promise((resolve, reject) => {
        const error = customValidationError(errorMessage, value, path, {
          min: minDate
        });
        value amp;amp; moment(value).isBefore(minDate) ?
          reject(error) :
          resolve(true);
      });
    });
});  

И использовать эти методы:

 const birthdate = yup.date()
  .typeError('INVALID_DATE')
  // Note tham I'm passing a function to be executed when validating date
  .dynamicMinDate('birthdate', 'MIN_AGE', () => {
    return moment().startOf('day').subtract(115, 'years').toDate();
  })
  .dynamicMaxDate('birthdate', 'MAX_AGE', () => {
    return moment().endOf('day').subtract(18, 'years').toDate();
  });