Hacker0x01 / react-datepicker

A simple and reusable datepicker component for React
https://reactdatepicker.com/
MIT License
7.89k stars 2.23k forks source link

Input time is not working when the format is European [dd/MM/yyyy h:mm aa] #4414

Open ChristianReynaltt opened 6 months ago

ChristianReynaltt commented 6 months ago

Describe the bug

When the only dateFormat property is default [MM/dd/yyyy h:mm aa] and, for instance, the input text has this value 12/13/2023 20:00, this value is being converted to 12/13/2023 8:00 PM --> ✅

Another examples:

BUT, when the dateFormat property is changed to European format [dd/MM/yyyy h:mm aa], the value is converting something wrong depending on 2 situations:

[Situation 1] For example. if today is 15/12/2023 [dd/MM/yyyy] and we set previous days --> the time is correct but he day is being replaced by the month (wrong)

It seems to me only the first number is being set in the input time.

To Reproduce

Steps to reproduce the behavior:

  1. Set your component such as first screenshot in your code
  2. Replace the dateFormat property by "dd/MM/yyyy h:mm aa" --> dateFormat="dd/MM/yyyy h:mm aa (copy this)
  3. Delete the time and type any some hour but in 24h format such as second picture
  4. See error as we described in hte first point.

Screenshots

EXAMPLE HERE: codeSandbox

image

Desktop:

freddyval7 commented 6 months ago

Same here.

pedro757 commented 6 months ago

This is blocking me, mine has dd-MM-yyyy and it behaves as MM-dd-yyyy

balajis-qb commented 6 months ago

Hi @ChristianReynaltt, I tried recreating the scenario. But it's working fine for me. Only when I type time in 24-hour time, it's parsing that as wrong 12-hour time value (But I think as the time format is set to 12hr, it's because of that).

() => {
  const [startDate, setStartDate] = useState(new Date());
  return (
    <DatePicker 
        selected={startDate} 
        onChange={(date) => setStartDate(date)} 
        timeInputLabel="Time: "
        dateFormat="dd/MM/yyyy hh:mm aa" 
        showTimeInput={true}/>
  );
};

I tried with the above code, I didn't face any issues with the date change. Only when I enter the time in 24-hour format, does it wrongly convert it. But if I give the data in the 12-hour format itself, it's taking it correctly. Is your issue regarding the time value alone?

ChristianReynaltt commented 6 months ago

Good morning @balajis-qb ,

"Only when I enter the time in 24-hour format, does it wrongly convert it" . It's the reason why some of us are talking about this issue. Even though data is made for 12-hour format and works fine, a lot of people here put the time in 24h format.

To summarise, If the dateFormat property is dateFormat="MM/dd/yyyy hh:mm aa" work fine when the input is set in 24h or 12h. but, when dateFormat="dd/MM/yyyy hh:mm aa" only works in 12h format.

Thanks my friend.

pedro757 commented 6 months ago

In my case I was using new Date("dd-MM-yyyy") making the component behave like MM-dd-yyyy, now I use parse() from date-fns to get the right date from that format, it works

ChristianReynaltt commented 6 months ago

@pedro757 Could we have some example please?

pedro757 commented 6 months ago
<ReactDatePicker
   onChange={handleChangeDel}
   dateFormat={"dd-MM-yyyy"}
   selected={new Date("31-12-2023")} // This will fail, use date-fns instead
   selected={new Date("12-01-2023")} // This won't fail but It will behave like MM-dd-yyyy
/>

I would create an util function like this:

function parseDate(myDate: string): Date {
  return parse(myDate, "dd-MM-yyyy", Date.now());
}

<ReactDatePicker
   onChange={handleChangeDel}
   dateFormat={"dd-MM-yyyy"}
   selected={parseDate("31-12-2023")}  // this works ✅
/>

So, it's not a react-datepicker's error but a javascript's one

ChristianReynaltt commented 6 months ago

Hi everyone, I've made a CodeSandbox (https://codesandbox.io/p/sandbox/wizardly-ganguly-mdkk2f?file=%2Fsrc%2FApp.js%3A22%2C19) because I tried @pedro757 solution and it's still not working.

Steps to reproduce the wrong behavior:

  1. I have the European format
  2. Delete ONLY the time and type any some hour but in 24h format such as this image image

BUT, when the dateFormat property is changed to European format [dd/MM/yyyy h:mm aa], the value is converting something wrong depending on 2 situations:

[Situation 1] For example. if today is 15/12/2023 [dd/MM/yyyy] and we set previous days --> the time is correct but he day is being replaced by the month (wrong)

Input value typed: 14/12/2023 20:00 ->12/14/2023 8:00 PM ❌ Input value typed: 07/12/2023 14:00 ->12/07/2023 2:00 PM ❌ Input value typed: 01/12/2023 19:00 ->12/01/2023 7:00 PM ❌

[Situation 2] For example. if today is 15/12/2023 [dd/MM/yyyy] and we set next days --> the time is wrong but now the day is correct.

Input value typed: 16/12/2023 20:00 ->16/12/2023 2:00 AM ❌ Input value typed: 20/12/2023 14:00 ->20/12/2023 1:00 AM ❌ Input value typed: 30/12/2023 19:00 ->30/12/2023 1:00 AM ❌ It seems to me only the first number is being set in the input time.

hugoburguete commented 2 months ago

@ChristianReynaltt I had a look into this one and it seems like react-datepicker uses the date-fns package to parse dates. The package checks the validity of the input and runs it past the date format you passed in.

Given that that you've passed the hours with lowercase h, it thinks that the hours you want to pass in are from 0-12. If you insert anything higher than 12, it'll do its best to determine the correct hours, hence why for 20:00, the output will be 2:00. If you change your date format to MM/dd/yyyy H:mm aa or MM/dd/yyyy HH:mm aa instead, it should work.

I was able to track this issue in the date_utils file. The parsedDate variable resolves to Invalid date.

You can find more details in the date-fns documentation for date formats and such.

Hope that helps.

aritzcmz commented 2 months ago

Hello @hugoburguete, the issue is with the day and the month order. If you use the format dd/MM/yyyy h:mm aa , and you try yo input a date like 03/12/24, it shows correctly: image

but as soon as you type an extra character that implies an incorrect date it changes the order to:

image

We understand that the date-fns package tries to calculate the date but it doesn't need to change the day/month order.

hugoburguete commented 2 months ago

Hi @aritzcmz

Your issue is still closely related to my last response. When checking the date validity, the package checks for a portion of the dateFormat and attempts to validate that. e.g. when you insert 03/12, the package validates that against the dd/MM. So in the scenario you've described:

And because the date is invalid, the default date parser used is the native browser Date API, which means: new Date('03/12/24 ') will resolve to Tue Mar 12 2024 00:00:00 GMT+0000 (Greenwich Mean Time).

If you were to type 03/12/202 or 03/12/2024, the day and month would not change.

If you wish the second scenario to pass, I assume your date format should be dd/MM/yy h:mm aa, not dd/MM/yyyy h:mm aa.

aritzcmz commented 1 month ago

Hi again, @hugoburguete, understood. And when we fill the data correctly it seems to work ok. The thing is that as soon as the data has an error, the default date format (we need the spanish hour default) changes the day and the month order. We even added the locale prop in order to tell the component to pick that as a default time format but does not work. Is there any way for it to not pick the english date format as a default?

hugoburguete commented 1 month ago

Hi @aritzcmz

Unfortunately, the Date API only supports a handful of formats:

Note: You are encouraged to make sure your input conforms to the date time string format above for maximum compatibility, because support for other formats is not guaranteed. However, there are some formats that are supported in all major implementations — like RFC 2822 format — in which case their usage can be acceptable. [...]