react-datepicker icon indicating copy to clipboard operation
react-datepicker copied to clipboard

Not able to set default time zone for date picker

Open HariSoni87 opened this issue 5 years ago • 52 comments

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

HariSoni87 avatar Jun 17 '19 13:06 HariSoni87

Facing the same issue.

neerajtomar98 avatar Sep 11 '19 12:09 neerajtomar98

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.

stephent avatar Feb 26 '20 22:02 stephent

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.

JohnStarich avatar Feb 27 '20 00:02 JohnStarich

This is definitely still an issue. Any chance we'll get some word on this?

MCBama avatar Apr 27 '20 16:04 MCBama

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.

neerajtomar98 avatar Apr 27 '20 19:04 neerajtomar98

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.

stale[bot] avatar Oct 24 '20 20:10 stale[bot]

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.

JohnStarich avatar Oct 24 '20 22:10 JohnStarich

Yep, we really need this too.

danielo515 avatar Nov 09 '20 18:11 danielo515

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.

dzmitry-kankalovich avatar Nov 10 '20 22:11 dzmitry-kankalovich

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 avatar Dec 10 '20 17:12 swkre

@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.

stephent avatar Dec 10 '20 20:12 stephent

+1 for UTC.

talovicnedim avatar Jan 07 '21 23:01 talovicnedim

Нужно TZ

renderlife avatar Jan 28 '21 08:01 renderlife

@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 avatar Jan 31 '21 02:01 JohnStarich

@JohnStarich how would you go about with setting the possible offset? I guess that would needed to be done internally with react-datepicker?

tlehtimaki avatar Feb 18 '21 19:02 tlehtimaki

@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 avatar Feb 19 '21 02:02 JohnStarich

@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.

tlehtimaki avatar Feb 19 '21 07:02 tlehtimaki

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 set startDate=2021/02/24 13:45 UTC+02:00 for 1:45pm UTC+2, then it's internally transformed into startDate=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.
  • 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 the UTC + 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=.

JohnStarich avatar Feb 25 '21 05:02 JohnStarich

@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.

JohnStarich avatar Feb 25 '21 05:02 JohnStarich

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. 🤔

tlehtimaki avatar Mar 03 '21 13:03 tlehtimaki

Same issue. I would like to always be using UTC if possible

tomhands1 avatar Mar 18 '21 14:03 tomhands1

@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.

JohnStarich avatar Mar 21 '21 20:03 JohnStarich

Would be great if it will be added

mordgard avatar May 17 '21 19:05 mordgard

I am looking forward to this fix.

55enokky avatar May 20 '21 02:05 55enokky

Feel free to open a pull request to make an attempt to fix this.

martijnrusschen avatar May 20 '21 09:05 martijnrusschen

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

ItzaMi avatar Jul 21 '21 17:07 ItzaMi

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 avatar Aug 10 '21 05:08 tmaximini

@tmaximini would you care to share an example of usage with react-datepicker or are you using it with it?

tlehtimaki avatar Aug 10 '21 16:08 tlehtimaki

+1 to support it from the library itself

gaurav1008 avatar Aug 26 '21 23:08 gaurav1008

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

DanielPortillo28 avatar Sep 10 '21 20:09 DanielPortillo28