wojtekmaj / react-calendar

Ultimate calendar for your React app.
https://projects.wojtekmaj.pl/react-calendar
MIT License
3.55k stars 515 forks source link

Timezone Handling #135

Closed rlugge closed 6 years ago

rlugge commented 6 years ago

Is there any chance of making the calendar timezone aware?

I'm currently having to write code like follows to strip out the (wrong) time data produced because the calendar is pulling from my local timezone, and not from a defined timezone that will vary with the input data. The app in question involves disparate locations, and those locations won't always be in the same timezone as the user. So I'm writing weird code like:

loadCalendar = (time) => {
  const date = moment(time).format('YYYY-MM-DD');
  const start = moment.tz(date, this.props.business.timezone).startOf('month');
  const end = moment.tz(date, this.props.business.timezone).endOf('month');
  ...//Business logic to query data between start and end of month
}

I'm having to cast the time provided by the calendar (the first second of the month) into a string, in order to re-create it using a timezone aware format.

An example of this creating a bug would be if I were in the EST time zone, and the location whose calendar I was managing was in PST. When selecting a new month, the calendar would produce the timestamp "October 1st, 00:00" When converted to the business's timezone, that produces "September 31st, 21:00".

Current behavior: calendar defaults to current user's timezone.

Desired behavior: calendar defaults to current user's timezone, but it's possible to tell it to use a different timezone instead.

wojtekmaj commented 6 years ago

Timezone conversion is a too complex task to handle by a simple widget which React-Calendar aims to be. As there are other, well tested solutions (like the very one you're using) out there, I don't think it would be good to include yet another one in this library.

Fuzzypeg commented 2 years ago

I don't see React-Calendar as a simple widget. It has complex knowledge of times and dates, including knowledge of local timezone which it obtains from the browser (via JS Date object).

Sure, we can do manipulations of input and output values like @rlugge does, but this can't solve every problem. For instance, today's date (highlighted in the calendar) is displayed as the local timezone's date. It may be 28 Oct where I am and still 27 Oct in UTC, for instance, but there doesn't seem to be a way to force "today" to display as 27 Oct if I want to use UTC.

External solutions can never make the calendar behave fully as though it's operating in a different timezone; and external solutions are messy and feel like a hack, since we're pretending the calendar is something it isn't. I recognise that there would be some work in this, but I believe timezone support would be a valuable addition to this already excellent library.

lgonzalez-silen commented 8 months ago

If I pass

  value={'2023-02-01'}

I expect the calendar to know what date I'm talking about regardless of timezone.

Showing 2023-01-31 just because I happen to be at tz -5 is a pain.

I don't think the request is to handle timezones. The request is to treat dates as dates. I realize new Date() gives you something else, and perhaps the calls to getTime() internally to check equality make things weird. Internally, dates can be represented whichever way you want, including a UTC timestamp, but the input should not make any assumptions about a user being in the 'right' timezone or force the user to guess what the right timezone is.

If this is expected, the need to massage value should be prominent in the readme.

(Thank you for all your work! Highly appreciated.)

lgonzalez-silen commented 8 months ago

For anyone else getting here, I fixed my beginning of the month calendar displays by doing

  value={moment(date).utcOffset(0).toDate()}

where date is a string in YYYY-MM-DD format.

Without moment, a couple of ugly options:

  value={Date.UTC(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate())}

or

  value={Date.parse(date + 'T00:00:00.000Z')}
silverwind commented 3 months ago

A calendar date is a timezone-independant value. I recommend to use Temporal.PlainDate when dealing with dates, which reinforces this idea:

https://tc39.es/proposal-temporal/docs/plaindate.html