Currently datepicker (inadvertently?) gives one a date set to the beginning of day in the users current local timezone. I. e. if you live in GMT+2 the moment will be set to two hours before the beginning of day in UTC.
Currently the only way to avoid this is to initialize the object with a moment object that is e. g. set to UTC like passing Moment.utc(); as selected.
I need the user to pick a UTC date and to show him an empty field if he hasn't done, so the above workaround is not an option.
Would it be possible to add a utc flag to the options that forces react-datepicker to interpret and return dates only based on utc so that I can do timezone conversion outside if I wish to?
Hey @lgrapenthin, it's very much intentional that the date is at the beginning of the day (since the component is time-agnostic it's the only thing that really makes sense). If we were to add an option it would probably be better to specify an offset rather than a UTC flag (docs), but another possible workaround is to set UTC globally with moment.utc() (docs) to make the empty case work.
This is why the picker being timezone agnostic highly irritates me:
Consider a birthday - Daytime has no meaning in this context. You don't know in what timezone the user was born, just the one in which he tells you about it. Yet react-datepicker merges those two facts of which only one is desired information into one piece of data: A moment object set to the users birthday in the timezone he recited it. Why would I want this?
This is why the picker being timezone agnostic highly irritates me:
- The component is supposed to let the user pick a calendar date, not a point in time. A calendar date is defined by Wikipedia as reference to a particular day within a Calendar system.
- Being able to pick a calendar date is the minimum requirement to any datepicker. Everything else, like adding daytime, casting timezones etc. can be done without a datepicker. If the datepicker also has such capabilities that is great, but it shouldn't make this minimum usecase anymore difficult.
- At the time react-datepicker makes this very difficult by forcing one to convert the picked date from the users local timezone back.
- Whether the fact that users pick dates in different timezones is relevant to the meaning of the date picked entirely depends upon on what kind of information that date is supposed to specify and as such should be library users choice.
Consider a birthday - Daytime has no meaning in this context. You don't know in what timezone the user was born, just the one in which he tells you about it. Yet react-datepicker merges those two facts of which only one is desired information into one piece of data: A moment object set to the users birthday in the timezone he recited it. Why would I want this?
- I. e. consider user1 has picked his m1 in USA, user2 has picked his m2 in GER, both via react-datepicker - Only knowing each users local timezone allows me to determine the calendar dates those users meant when they picked them in the UI.
Hey @lgrapenthin, I'm very much familiar with the purpose of a date picker, but if this behavior "highly irritates" you, please submit a fix; lecturing us with a tone like that without any inclination for contributing a fix isn't going to get you much sympathy. In my original reply I attempted to give you a workaround** and I told you what I think the fix should look like. Unfortunately the default behavior has caused you grief, but it is within _your_ power (yes, you!) to help yourself and all the other consumers of this component.
** Looks like you would actually need moment timezone to set the global timezone
@rafeememon I am truly sorry if my comment offends you, which was not my intent at all. I haven't addressed you directly as my comment was not a direct response to yours. I have had time today to think about the issue more deeply and aside from improving the title I took a bit time to research the issue and provided additional arguments why the current default behavior can appear as highly irritating and an opt-out would be desired. Please consider those as a contribution instead of a lecture you were not asking for.
I don't see why you'd want me to program something before it is agreed upon with the maintainer which I am not sure you are. I don't know how development of this tool is organized and as such I couldn't infer from your comment that it was to be understood as a feature decision and implementation request - especially since you used the word _probably_. I am not a JavaScript programmer, instead using JS from a compile-to-JS language via interop so I leave writing quality JavaScript to those who are capable of it.
Certainly I am not here for sympathy but instead because I value this tool and wish to help improving it. Please consider my comments here as my main contribution so far.
Altering global defaults affects other codes behavior, so it is not a viable workaround to me. I believe the only workaround at the time is to manually calculate the difference to the users timezone and adding it back.
@lgrapenthin -- I'm sorry for misinterpreting your comments; perhaps the miscommunication was because we're both passionate about code and making things work correctly. The arguments you gave make it clear that this is an issue with no good workarounds. I think often it's pretty easy to lose sight of what something is actually being built for and how it will be used, and having concrete examples is hugely valuable. I want to make sure we have a good answer for all of the points you bring up before we settle on a solution.
I am indeed a contributor and I would like to get a fix for this landed. Re: design decision -- I used "probably" only as a way of brainstorming; the idea I had gives extra flexibility but I'm not sure if the added flexibility has any motivating use cases. I ask for contributions for all requests as I'm only able to contribute here in my spare time, which I haven't had a lot of lately because of "real" work. I believe to an extent that if one can give a detailed description of a problem, they can also fix the problem =) Don't forget that you're not alone, and we will give you direction and code review comments if you decide to take a crack at this. This is one of the greatest benefits of open source!
If I understand the workaround correctly, I'm not getting the results I was expecting.
const rightNow = new Date().getTime(); // run at ~2:30pm EST == 1472668275653
const startTime = moment.tz(rightNow, "Australia/Melbourne");
return (
<DatePicker
className="form-control"
dateFormat="YYYY-MM-DD"
selected={ startTime }
onChange={ this.handleDateChange }
/>
);
I'm still getting today's date, when I should be getting tomorrow when setting the timeZone to "Australia/Melbourne" (It's currently ~4:30 am there right now). Is this more or less the recommended path? Am I missing something? Really don't mind workarounds, just feel like I've wandered off the reservation a bit and would love a suggestion.
EDIT: Correction, it works... sort of. If I trigger the calendar view by selecting the text component, then it will highlight the correct date without me selecting it. After de-focusing the control, the text field will display the correct date and everything seems to work fine. You might already have a solution here with a small state problem at initialization. Let me know if I can be of any help.
ANOTHER EDIT A little further down the rabbit hole:
If I add the following code in my parent component where the date picker has a ref of dateRow:
componentDidUpdate() {
this.refs.dateRow.refs.input.focus();
setTimeout(() => {
this.refs.dateRow.handleInputDone();
}, 0);
}
And I change the timezone from UTC to Melbourne's I can click anywhere (including outside the browser window itself) and the date will update as expected. I tried running the module locally using npm link, but I ran into a lot of issues with hot loading and my current project so I was unable to troubleshoot with the code on my machine.
From there I shortened the componentDidUpdate function to the following and everything seems to work:
THIS WORKS
componentDidUpdate() {
this.refs.dateRow.refs.input.handleBlur();
}
render() {
const rightNow = new Date().getTime(); // run at ~2:30pm EST == 1472668275653
const startTime = moment.tz(rightNow, "Australia/Melbourne");
return (
<DatePicker
ref="dateRow"
className="form-control"
dateFormat="YYYY-MM-DD"
selected={ startTime }
onChange={ this.handleDateChange }
/>
);
}
Seems like this might be fixed now?
Yes, I hope. if this is not in release you can use workaround: include utcOffset={moment().utcOffset()} property and it will fix it.
I pushed 0.40.0 with the fix included.
Sorry, I did not know that you are a maintainer. Thanks
No problem :)
Thank you all, this was annoying the * out of me. I like the behavior much better now.
Im using react-datepicker": "^0.49.0"
and on the todayButton={"Today"} im still getting yesterdays date.
I share my "fix" here:
My goal was to keep current datepicker behavior (work in UTC is nice) and change only when date is push to other services (a cassandra database for me).
To convert date to user wishes, I have to move date as below :
let utcOffsetMinute = moment().utcOffset();
data.companyBirthDate.add(utcOffsetMinute, 'minutes').utc();
If user select 2012-01-10 at GMT+2, react-datepicker will store 2012-01-09T22:00:00Z. I'll change value to 2012-01-10T00:00:00Z before storing it.
@dbyzero I think the latest release may have switched some dates back to UTC by accident. We might need more unit tests.
Hmm, do we know which commit broke this? And yes, more tests..
@martijnrusschen I've been busy on other things and haven't had a chance to test, but I think b1615d8fbed00db3bf1dc2ead3cf03585fdb5b73. Note that utcOffset is set via defaultProps, so in most timezones will be truthy by default, preventing the next line for local moments from being used.
Can confirm that the latest version gives yesterdays date for timezones east of GMT.
@martijnrusschen Can you reopen this?
Wouldn't have it been more appropriate to add a typeof wrapper for the utcOffset instead of plain revert?
Or were there any other side effects not accounted for?
Hey, is this issue still happening for more users?
Most helpful comment
This is why the picker being timezone agnostic highly irritates me:
Consider a birthday - Daytime has no meaning in this context. You don't know in what timezone the user was born, just the one in which he tells you about it. Yet react-datepicker merges those two facts of which only one is desired information into one piece of data: A moment object set to the users birthday in the timezone he recited it. Why would I want this?