date-fns: Can't resolve RangeError: Format string contains an unescaped latin alphabet character `n`

Currently facing this error from a functional component using date-fns. Here is the component I created.

`import 'date-fns';
 import React, { useState } from "react";
 import Grid from '@material-ui/core/Grid';
 import DateFnsUtils from '@date-io/date-fns';
 import {
    MuiPickersUtilsProvider,
    KeyboardDatePicker,
} from '@material-ui/pickers';

const DatePicker = ({ date, onChange,label})=> {

    return (
        <MuiPickersUtilsProvider utils={DateFnsUtils}>
            <Grid container justify="space-around">
                <KeyboardDatePicker
                    disableToolbar
                    variant="inline"
                    format="MM/dd/yyyy"
                    margin="normal"
                    id="date-picker-inline"
                    label={label}
                    value={date}
                    onChange={onChange}
                    KeyboardButtonProps={{
                        'aria-label': 'change date',
                    }}
                />
            </Grid>
        </MuiPickersUtilsProvider>
    );
}
export default DatePicker;`

Then I call the components and provide the props I declared.

import React, { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import DatePicker from "../artifacts/Calendar/Calendar";


const defaultValues = {
    StartDate: "",
    EndDate: "",
    TextField: "",
    Select: "",
    Checkbox: false,
    PlatformToSearch: "",
};

const SearchBar =()=> {

    const [data, setData] = useState(null);
    const { handleSubmit, register, reset, control } = useForm({ defaultValues });
    const [selectedStartDate, setSelectedStartDate] = useState(new Date('2014-08-18T21:11:54'));

    const handleStartDateChange = (date) => {
        setSelectedStartDate(date);
    };

    const onSubmit = data => {
        console.log("Data:",data)
        setData(data)
    };

    return (
        <div>
            <form onSubmit={handleSubmit(data => onSubmit(data))}>
             <div className="flex">

                <DatePicker 
                label="START DATE"
                value={selectedStartDate}
                onChange={handleStartDateChange}
                />
                </div>
            </form>
        </div>
    );
}

export default SearchBar;

package.json

`
"dependencies":
 {
    "@brightleaf/react-hooks": "^4.2.0",
    "@date-io/date-fns": "1.3.13",
    "@material-ui/core": "^4.0.0-rc.0",
    "@material-ui/pickers": "^3.2.10",
    "date-fns": "2.13.0",
    "isomorphic-unfetch": "^3.0.0",
    "react": "^16.13.1",}`

Any help is appreciated

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 15
  • Comments: 18 (3 by maintainers)

Most upvoted comments

Any luck with this error?

I debugged the provided codesandbox and concluded that this is not a bug in the date-fns code.

The React code eventually provides date-fns format() function undefined as the second parameter; however, the second parameter is required and should be a format string of type String.

In the codesandbox demo the format() function converts undefined to a string with a text value of undefined. Then the format string validation block executes against the string value undefined as the format string, one character at a time. The u character is considered a valid format character (determined by longFormattingTokensRegExp) but n is not, so a RangeError is thrown mentioning the latin character n.

An improvement would be for date-fns format() to check the type of the second parameter to ensure that it is of type string and non-empty.

@roysantu2002

I think it was explained well already here https://github.com/date-fns/date-fns/issues/1857#issuecomment-807272204 but I wanted to add a few things.

The format function requires you to wrap non-token latin characters (a-zA-Z) in single quotes if you want to use those as literals. The second format argument gets converted to a string right away internally. If that argument is null or undefined, it will become the string "null" or "undefined" and throw a RangeError because of the presence of the non-token n character in those words.

https://github.com/date-fns/date-fns/blob/ea3f05069605388af0bb6a27f8cf4539f3d70db6/src/format/index.js#L348-L351

Couple scenarios with v2:

import { format } from 'date-fns'

format(new Date(), "Pp") // "06/29/2021, 11:35 AM"
format(new Date(), "Pp 'n'") // "06/29/2021, 11:35 AM n"

format(new Date()) // TypeError: 2 arguments required, but only 1 present

format(new Date(), "Pp n") // RangeError: Format string contains an unescaped latin alphabet character `n`
format(new Date(), undefined) // RangeError: Format string contains an unescaped latin alphabet character `n`
format(new Date(), null) // RangeError: Format string contains an unescaped latin alphabet character `n`
format(new Date(), {}) // RangeError: Format string contains an unescaped latin alphabet character `o`

@kossnocorp A TypeError is thrown when the second argument is missing. Here, I think the issue is that you’ll get this seemingly unrelated RangeError when the format string is null or undefined (see above). So while it’s not a bug in the library, that internal string conversion is a bit sneaky and ends up obfuscating the real root cause of the bug in the program using the library.

I wanted to make a suggestion. Wouldn’t removing the string conversion in format potentially be a win for everyone? One less runtime check/conversion (it was no-op for the happy path anyways). Let it fail if it’s not a proper string, at least the runtime error would be easier to comprehend from a developer’s perspective. I believe it would fail on a .match() call internally, so they would receive something more logical like TypeError: Cannot read property 'match' of null instead.

I can confirm this is not fixed even with release 2.22.1.

@Dinnall, check out the demo: https://codesandbox.io/s/z9k3z

Your version of date-fns doesn’t match the demo’s. That might be it.

✅ For me, the only solution was downgrading the @date-io/date-fns version using yarn add @date-io/date-fns@1.3.13 or npm i @date-io/date-fns@1.3.13.

It seems working just with the V1.3.13 but not with the version 2.

I found if I use @date-io/date-fns2.x , there will truely occur the problem ‘Can’t resolve RangeError: Format string contains an unescaped latin alphabet character n’, and when I downgraded the version to 1.3.13, this problem has gone, but I meet another problem like ‘Can’t resolve RangeError: Format string contains an unescaped latin alphabet character o’,and it’s not every time, but occasionally, does anybody meet the same problem like me? I don’t know why and I wanna find the solution to fix this problem, thanks.

Hey everyone, sorry for the confusion. As @JeffBudaTR noted, this is not a date-fns issue. I can’t see the issue in the provided Sandbox, but I understand it correctly, date-fns throws an error when the format prop is missing. I would recommend opening an issue in Material UI and ask them to provide prop types for the component in question. Additionally, I would make sure that TypeScript definitions are present.

Regarding the @JeffBudaTR’s suggestion to validate the arguments. The thing is that we don’t want to make any runtime checks because those who want to have type safety can use TypeScript/Flow definitions, and runtime checks add a lot of extra bytes to the library, and one of our main goals is to make date-fns as light as possible.

I know that we have some runtime checks in the code already, but we will remove those upon complete transition to TypeScript in v3.

Please let us know if there’s anything else we can do.