react-datepicker
react-datepicker copied to clipboard
Not able to set default time zone for date picker
All the dates which we receive from date picker are in local time zone. Is there a way to define the time zone. In our application use case we want to get the date in server time zone in place user's time zone. React version - 15.6.2 React-datepicker version - 1.6.0
Facing the same issue.
As a workaround to this, I'm cheating the selected date by offsetting the actual date/time of my application's state by the utc offsets of the user's default time zone and the time zone my application is working in. Using moment-timezone.js:
const mo1 = moment(dateTime); // in browser default time zone, e.g. America/Denver
const mo2 = moment(dateTime).tz(myTimezoneId); // in current state time zone e.g. Africa/Bamako
const modifiedDate = moment(dateTime);
modifiedDate.subtract(mo1.utcOffset() - mo2.utcOffset(), 'minutes');
return modifiedDate.valueOf();
Then, in react date picker:
<DatePicker selected={modifiedDate} />
It would be nice to be able to set a time zone on react-datepicker directly so as to avoid having to do this.
I'm doing something similar to @stephent, and wrapped it up into a component to wrap DatePicker
. So far it's working pretty well, but I'd love for this to be built-in
Happy to contribute this logic if we get some buy-in on the idea.
This is definitely still an issue. Any chance we'll get some word on this?
This is definitely still an issue. Any chance we'll get some word on this?
Iam using a workaround for this issue. please check https://github.com/Hacker0x01/react-datepicker/issues/1388#issuecomment-582590792 But it will be good if there is prop in-built for this.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This seems like a fairly common problem, judging from the top comment reactions.
@martijnrusschen Is this something you want in react-datepicker? If so, I'd be happy to contribute something like a utc
option to store dates in UTC.
Yep, we really need this too.
Really need this feature, sometimes I have cases when I need a datepicker to deal with datetime of the specific fixed TZ as opposed to browsers local TZ.
For example, I live in LA, so it's PST TZ, but I want to select datetime of the schduled job to run in let's say Moscow local TZ, and I don't want to try to remember what would equivalent date time for Nov 11, 10 pm Moscow time in my loca TZ which is PST.
So by default the datetime would be selected in my local
PST TZ, and my workaround is to offset the selected value to the target
TZ in onClick event:
getTzOffsetMs() {
const targetTz = +3; // UTC+3
return (new Date().getTimezoneOffset() + (targetTz * 60)) * 60 * 1000;
}
toTargetTime(localTime) {
// substraction of offset gives results as if I was selecting date having target TZ as a local TZ in my browser
return localTime.getTime() - this.getTzOffsetMs()
}
toLocalTime(targetTime) {
return targetTime.getTime() + this.getTzOffsetMs()
}
onClickDatepicker(date) {
const targetTs = this.toTargetTime(date)
this.setState({
scheduled_at: targetTs, // the value I need
scheduled_at_dp: date.getTime() // the display value for Datepicker
})
}
Hope this makes sense. This though works reliably only if target TZ does not have Daylight Saving Time (DST).
Ideally though, I should be able to override TZ in Datepicker configuration properties.
Yes @martijnrusschen, it would be great if you can implement this as a built in property! @JohnStarich: Your UTC option would be perfect. We have an app where we would like the client's interaction to be in UTC.
@swkre @JohnStarich I think generalizing it beyond just UTC would be preferable. I have a use case where the time zone of the control should match the time zone of a location on the map (which could be anywhere). Being able to set a Timezone ID or UTC offset for the control would be ideal.
+1 for UTC.
Нужно TZ
@stephent I agree, more flexibility would be good. It seems a utcOffset
prop used to be available, but may have been removed when the underlying library changed (#1647).
For reference, my wrapper component for UTC is fairly simple, so I'll share below. Might be a good starting point for discussion.
If any contributors or maintainers could chime in, that would be much appreciated! 🙂
import React from 'react';
import DatePicker from 'react-datepicker';
function convertUTCToLocalDate(date) {
if (!date) {
return date
}
date = new Date(date)
date = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())
return date
}
function convertLocalToUTCDate(date) {
if (!date) {
return date
}
date = new Date(date)
date = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()))
return date
}
export default function UTCDatePicker({ startDate, endDate, selected, onChange, ...props }) {
return (
<DatePicker
startDate={convertUTCToLocalDate(startDate)}
endDate={convertUTCToLocalDate(endDate)}
selected={convertUTCToLocalDate(selected)}
onChange={date => onChange(convertLocalToUTCDate(date))}
{...props}
/>
)
}
Related: #1592, #1671, #2043, and possibly #1018.
@JohnStarich how would you go about with setting the possible offset? I guess that would needed to be done internally with react-datepicker?
@tlehtimaki Yeah, ideally this would all be done inside react-datepicker somewhere. I'm imagining a return of the utcOffset
parameter in some fashion could be a good solution. JS has a means of messing with Date objects and time offsets, so should be doable at that level.
Mainly waiting on buy-in from the maintainers before I swoop in with a PR. 🙂
@JohnStarich Thanks for getting back to me! 👍 I was considering if you would be interested to share the idea in a form of fork or the PR as I have many colleagues interested in this too. We are not planning to switch to a fork, but I could review, test and propose changes. So what do you think? I think the former utcOffset only worked if you did not set the date to begin with. I think it would be useful if we could provide a general utcOffset so that:
- date given is first perceived as local
- then it's converted to UTC+0000
- then the offset is applied
- offset is then used to set the context for the date picker
- after selection the time would also show with offset. Not sure how this would work. 🤔
I figure that the feature needs some documentation and I would scope it only to allow setting the offset manually, no full fledged time zone solution.
I haven't really dug into the internals of react-datepicker to be honest, though if we think it will make a difference then I can contribute a bit in my spare time 🙂
That's a great start 👍 As a set of general goals, does this sound reasonable? (Very similar to your list, above.)
- A new
utcOffset
property - Defaults to local time zone offset. Set to
0
for UTC,1
for UTC+1h, etc. - Inputs and outputs are in the same desired offset
- Internal logic can still assume we're using the local time zone (simplifies changes for a PR)
If those are reasonable, I think it might look like this in practice:
- If
utcOffset
is set, input dates (e.g.startDate
,endDate
) have their time offsets replaced with the local time zone before storing internally. We could either replace the offset or apply the difference, just need to assess the user experience.- Example: If
utcOffset=2
and I setstartDate=2021/02/24 13:45 UTC+02:00
for 1:45pm UTC+2, then it's internally transformed intostartDate=2021/02/24 13:45 UTC-05:00
or 1:45pm local time. - I think this will be easiest to use, since it will not require any special conversions from the internal date in end users' code. Input dates are simply assumed to be in the desired offset-time-zone.
- Example: If
- Since the inputs are converted internally, the UI elements will adjust the time based on the UTC offset.
- Output dates (e.g.
onChange
call args) are given an inverse transform from the internal local time zone into theUTC + utcOffset
form.
Time zone conversions are difficult for me, so I might've gotten these conversions wrong 😅
Maybe we can try to define the behavior with examples, since those are a little more concrete? In my case, I always want to use UTC on the server side for when a "day" starts at 0m0s. As long as my local dates appear to be the same as my server dates, then all is well with the world.
Here's a simplified and converted example from my project, where I'm selecting a month in the UI and need to send start/end dates to the server in UTC.
// Use today's local date, but replace time zone with UTC.
function firstOfMonth(date) {
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1))
}
function lastOfMonth(date) {
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0))
}
const [start, setStart] = React.useState(firstOfMonth(new Date()))
const [end, setEnd] = React.useState(lastOfMonth(new Date()))
React.useEffect(() => {
API.get('/v1/getBudgets', { params: { start, end } })
.then(res => res.data.Budgets),
.then(budgets => /* processing... */ )
}, [start, end])
return (
<DatePicker
utcOffset={0} // use UTC+0 for the UI elements
selected={start} // inputs are in UTC + utcOffset
onChange={v => { // outputs the selected time in UTC + utcOffset
setStart(firstOfMonth(v)) // select the whole month using UTC dates
setEnd(lastOfMonth(v))
}}
showMonthYearPicker
/>
)
Since it relies on server dates, we just ensure our inputs are always in our desired time zone and the UI will match that time zone with utcOffset=
.
@tlehtimaki, @stephent, @dzmitry-kankalovich would love to hear your thoughts on the above ^
Essentially the idea is to simply select and display dates/times in the chosen UTC offset, so all inputs and outputs do not need to be modified from their server-based sources.
Good thoughts there @JohnStarich, at least the foundations are somewhat clear. JS Date can be initiliazed from UTC, but challenge is that when using it its always in the local time. So with time zone this causes the challenge that we would need to fake the today in order to display it in the desired offset.
So when my local time would be UTC+3 and I select date at time 01:00 today it would still be yesterday in UTC0 if our offset would be 0, so the challenge would to show the UI according to the offset, not according to the local time. This can be done (I believe) in the way described that we offset all the times with the given number of offset hour/minutes, but somehow ignore the local time zone when displaying times.
What would the problems be we face here? moment solved the problem by handling time in its own objects. Maybe we could do something similar internal and then return the native Date object then as selected value, which user again needs to now that its displayed in local time. 🤔
Same issue. I would like to always be using UTC if possible
@tlehtimaki Makes sense to me 👍 I'm not familiar with the current logic, just anecdotally seems like it's using native Date objects for everything. If so, yep that could be problematic when supporting different output time zones.
If it were me, I think I'd try to store the date in unix time (seconds since Jan 1st 1970 UTC) internally, then convert to Date's when displaying or sending back to the user. That should make it a bit easier to convert between everything.
Would be great if it will be added
I am looking forward to this fix.
Feel free to open a pull request to make an attempt to fix this.
Is there a straight answer to this?
I'm trying to move away from momentJS
but it seems that any time
library or even the default JavaScript Date
has the same issue: everything that is UTC
is delivered as a string and ReactDatePicker
still needs a Date object
so that's no bueno.
I need to get my Date object
into the selected
prop as UTC
but no matter how many conversions I do, I always end up having to use toDate()
at the end (for the object) which brings me back to locale time
We're using date-fns-tz for this, which comes with two helper functions zonedTimeToUtc
and utcToZonedTime
which makes the transformation pretty easy. It returns a date object.
@tmaximini would you care to share an example of usage with react-datepicker or are you using it with it?
+1 to support it from the library itself
Hey team
We also have been facing several issues on this matter, we try to solved but everything turns to be huge work around, implementing a solution out of the component it is not good for production, we do really need this feature.
Thank you