是的,将最小最大日期与构建日期而不是当前日期进行比较

Yup compares min max date with build date instead of current date

所以这很奇怪,我无法理解它的来源。

我有一个注册 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.0yup 0.29.2

好的,所以我找到了解决方案。

事实上,Yup 会存储您最初提供的日期并进行编译。它将不再在您每次验证日期时执行 moment().endOf('day').subtract(18, 'years')

为此,您必须使用测试方法,而不是 minmax

我已经为 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 && 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 && 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();
  });