添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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 parse('1-12-12', 'yyyy-MM-dd', new Date()) returns a valid date parse('2-12-12', 'yyyy-MM-dd', new Date()) returns a valid date Oct 19, 2018

To add up to it, this also gets parsed just fine:

parse('1-12-2018', 'dd-MM-yyyy', new Date());

while I assume it to fail. It would only be parsed when pattern is d-MM-yyyy or if date string is explicitly 01-12-2018.

Otherwise, it somewhat kills the whole purpose of passing the pattern as it doesn't follow it strictly.

UPDATE: I have misread the original comment at first, it seems to outline the same exact issue.

You both have a fair point. We didn't put much thought into that but just tried to parse as many cases as possible.

Before we proceed to make parse strict, could you please tell about your cases where it caused troubles? Understanding the exact issue will help figure out the optimal solution. Thanks!

@kossnocorp Aside from this is how moment and luxon handle this kind of stuff, its useful to consistently control user input in one-way flow environments (e.g., react), where you update some state on every stroke (often the case). In that case its fine to allow strictly incorrect input, but the issue appears when an incomplete input is parsed as something valid.

E.g., simple use case: user enters 05-12-20 and its being immediately parsed as a valid date that is formatted with a strict pattern and ends up being 05-12-2020. But what the user really wanted to type is 05-12-2018, he just didn't have a chance to type the remaining 18 piece. Now the user backspaces one character and its immediately parsed to 05-12-0201, etc, and the story repeats.

I ended up using luxon for the current project just because of this, but will immediately switch back to date-fns once there is such capability (because date-fns is way more awesome API-wise).

I was building a date picker where you could either type or select a date on a calendar view. The calendar view would update to show the month with the entered date as selected immediately when the user finished typing a date. But because of this it would already move to the year 2, then 20, then 201 etc as the user was typing.

I fixed it by doing an input === format(parse(input, pattern), pattern) check.

The inability to do strict parsing also prevents my team from using date-fns. To illustrate the use case that @VasilioRuzanni and @OCJvanDijk mentioned, take a look at the first example here. The default date is today's date in the format MM/dd/yyyy. As an example, today's date is 03/04/2019. If you delete the last two digits from the year, you end up with 03/04/20. My intention may be to change the year from 2019 to 2018 by deleting 19. However, the parse function in date-fns accepts 20 as a valid year in the 4-digit year format yyyy. As a result, the calendar picker would change the date to March 4th, 2020.

To add to the use-cases:

We use parse as part of some custom validators in our angular app where dd/mm/yyyy is the only accepted format - using parse handles other parts of the validator but we've had to introduce an additional regexp test to ensure the correct format before passing through to date-fns for parsing.

Not the end of the world but would be good if parse actually enforced the format being passed in

The current hack you can do is to check whether the string is the same length as the format:

import parse from 'date-fns/parse';
import isDate from 'date-fns/isDate';
import isValid from 'date-fns/isValid';
 * Parse a string as a Date object
 * @param {string} str String to parse
 * @param {string} format Format of the date (see date-fns formats)
const parseDate = (str, format) => {
  // This condition is necessary since date-fns doesn't strictly parse the dates
  // anymore:
  // https://github.com/date-fns/date-fns/issues/942
  if (str.length !== format.length) {
    return undefined;
  const parsed = parse(str, format, new Date());
  if (isDate(parsed) && isValid(parsed)) {
    return parsed;
  return undefined;
          

I am amazed that this ticket is still open three years after it was reported.

If I specify that a user should enter a date using the format 'dd/MM/yyyy' that's what I mean, not 'dd/MM/yy' too!

I only installed date-fns today and parse() was the first function I tried.

Sorry - but I'm sticking with moment.

I think we just need to add strict parsing as option. Current behaviour of parsing most of the cases possible seems to me correct.

If you look in Java parse does the same: For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.. https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/SimpleDateFormat.html

But the Javascript specs ( https://www.unicode.org/reports/tr35/tr35-dates.html#Parsing_Dates_Times) say In most cases the length of the y field specifies the minimum number of digits to display, so I would expect parse to fail as you expect at least 4 digits.

So to meet both worlds, probably would be great to have:

  • Non strict parse as parse("23-04-23", "dd-MM-yyyy", new Date()); // = Sun Apr 23 0023 00:00:00 GMT+0144 (EET)
  • Strict parse as parse("23-04-23", "dd-MM-yyyy", new Date(), {strict: true}); // = Invalid Date.
  • I think this has to be sorted out sooner than later.

    To give some context, and a use case where strict parsing would be needed, we have a Date Picker component that supports multiple parsing formats simultaneously: you can provide it with a list of formats used for parsing setDateFormats("yyyy-mm-dd", "yy-mm-dd"), and the idea is that it'll parse the date entered by the user using the first matching format.

    The problem that this issue is causing us is that yyyy-mm-dd now parses a string like 42-12-30 as 0042-12-30, while yy-mm-dd parses it as 1942-12-30, so the resulting date depends on the order in which the formats were provided. Of course we can instruct developers to work around this, but 1. nobody reads documentation and 2. it's really annoying to have to keep track of that as a developer. (To make things worse, the first format in the list is also used as the display format, so currently you can't even reverse the order if you want to display the value with 4 digit years.)

    I would also love to see an exact option of function. The current one is just confusing.

    I need to extract the year from a string that has one of a few possible formats. My current workaround is to precheck the string with a regex. See my code below

    import * as dateFns from "date-fns";
    const parseYear = (string) => {
        let date;
        if (/\d{4}/.test(string) && dateFns.isMatch(string, "y")) {
            date = dateFns.parse(string, "y", new Date());
        } else if (/\d{1,2}\.\d{1,2}\.\d{4}/.test(string) && dateFns.isMatch(string, "d.M.y")) {
            date = dateFns.parse(string, "d.M.y", new Date());
        } else if (/\d{1,2}\/\d{1,2}\/\d{4}/.test(string) && dateFns.isMatch(string, "M/d/y")) {
            date = dateFns.parse(string, "M/d/y", new Date());
        } else if (/\d{4}-\d{1,2}-\d{1,2}/.test(string) && dateFns.isMatch(string, "y-M-d")) {
            date = dateFns.parse(string, "y-M-d", new Date());
        if (!dateFns.isValid(date)) {
            throw new Error(`Invalid year string: ${string}`);
        return dateFns.getYear(date);
    console.log(parseYear("2000"))
    console.log(parseYear("200"))