Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Date validation failure. #2458

Open
lgnl272 opened this issue Nov 24, 2022 · 11 comments
Open

Date validation failure. #2458

lgnl272 opened this issue Nov 24, 2022 · 11 comments

Comments

@lgnl272
Copy link

lgnl272 commented Nov 24, 2022

Your environment

  • Version of JQV: 1.19
  • Browser name and version: Google Chrome 107.0.5304.107 (Build oficial) (64 bits)

Current behavior

Validator allows any kind of dates even considerating day 30 in February

Expected behavior

Validator must return an error message.

Live demo

Try to validate 1983-02-30 and validator doesn't show anny error message

@RobJohnston
Copy link
Contributor

I believe that you used the Date method, which has been deprecated in favour of DateISO. I get that from the comment in
#1845.

@lgnl272 lgnl272 closed this as completed Nov 26, 2022
@lgnl272 lgnl272 reopened this Nov 26, 2022
@lgnl272
Copy link
Author

lgnl272 commented Nov 26, 2022

I'm using the DateISO method

@bytestream
Copy link
Member

@lgnl272 Please provide a jsfiddle link

@wewhite
Copy link
Contributor

wewhite commented Jan 6, 2023

Duplicate bug: #276
DateISO only does structure checks, where 1983-02-30 is a valid DateISO structure.
It is an invalid Date.

@wewhite
Copy link
Contributor

wewhite commented Jan 6, 2023

I find it interesting that the 'date' validator is deprecated in favor for date ISO which is a standard notation/format.
There is no way to verify that the date is valid in time using ISO notation.

Probably need to implement ISO week date which is part of ISO 8061 so the date can be checked for two(2) things:

  • valid ISO notation
  • valid date/time exists

DateISO should be named DateISO8061 or DateISOFormat, then de-depricate the 'date' validator.

Date validator correctly errors on new Date('1983-02-30') as it should.

@RobJohnston
Copy link
Contributor

Reminds me of an old pull request: #2032

@wewhite
Copy link
Contributor

wewhite commented Jan 6, 2023

return this.optional( element ) || ( !/Invalid|NaN/.test( new Date( value ) ) && /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value ) );

adding the !/Invalid|NaN/.test( new Date( value ) check fixes the current use case.
Basically copied the test case for date: (that is being deprecated) and logically AND it with dateISO format.

Screen shot of test cases:

Screenshot 2023-01-06 at 3 07 55 PM

@wewhite
Copy link
Contributor

wewhite commented Jan 6, 2023

new Date (dateString) format includes date-only forms:
where dateString can be one of:

  • "YYYY"
  • "YYYY-MM"
  • "YYYY-MM-DD"

YYYY-MM-DD follows exactly as a Date only ISO format (not including time).
new Date(dateString) is ISO-8061 compliant.
Quote from MDN web docs "This is ISO-8601-compliant and will work reliably"

I'll add a push and create a pull request.

@wewhite
Copy link
Contributor

wewhite commented Jan 9, 2023

Disregard the above, I now see the problem with Date() and how different browsers interpret.
Bigger problem with JavaScript, not jquery-validate.

@wewhite
Copy link
Contributor

wewhite commented Mar 8, 2023

ChatGPT came up with this code, and it works for me in Firefox, Safari and Chrome.

/**
 * Checks if a given string is a valid date in the format MM/DD/YYYY.
 * @param {string} dateString - The string to validate.
 * @returns {boolean} True if the string is a valid date, false otherwise.
 */
function isValidDate(dateString) {
  const dateFormatRegex = /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/;

  // Check if the string matches the expected date format.
  if (!dateString.match(dateFormatRegex)) {
    // The string does not match the expected format.
    console.log( "The string does not match the expected format.");
    return false;
  }

  // Split the string into its component parts.
  const [year, month, day] = dateString.split('-').map(part => parseInt(part));

  // Check if the month is valid.
  if (month < 1 || month > 12) {
      console.log( "The month is not valid.");
    return false;
  }

  // Check if the day is valid for the given month and year.
  const daysInMonth = getDaysInMonth(month, year);
  if (day < 1 || day > daysInMonth) {
        console.log( "The day is not valid.");
    return false;
  }

  // The string is a valid date.
  return true;
}

/**
 * Returns the number of days in the given month for the given year.
 * @param {number} month - The month (1-12).
 * @param {number} year - The year.
 * @returns {number} The number of days in the given month for the given year.
 */
function getDaysInMonth(month, year) {
  if (month === 2 && isLeapYear(year)) {
    return 29;
  }
  return [31,28,31,30,31,30,31,31,30,31,30,31][month - 1];
}

/**
 * Checks if the given year is a leap year.
 * @param {number} year - The year.
 * @returns {boolean} True if the year is a leap year, false otherwise.
 */
function isLeapYear(year) {
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}

@wewhite
Copy link
Contributor

wewhite commented Mar 8, 2023

Here is a jsfiddle: JS Fiddle 'isValidDate'

I have added a test case, grunt completes successful, all tests pass.

Questions:
I have created a new validator named 'isValidDate' using DateISO standards, should my new validator replace dateISO?
Should I submit PR as is, or wait for the above question answered?

I think this solution will close a lot of date issues.

@bytestream bytestream changed the title Date validation failure. D Date validation failure. Jun 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants