4

If selected starts out as null.

When I select a date 20/04/2022

Datepicker shows 20/04/2022

Console.log shows Wed Apr 20 2022 00:00:00 GMT+0200 (Central European Summer Time)

But my payload on the form shows 2022-04-19T22:00:00.000Z

Can I lock the format to UTC?

ComCool
  • 773
  • 4
  • 15
  • 28
  • UTC isn't a format, it's a timezone. Both strings actually represent the same `Date` object and were probably created by the same object - one is the human-readable form, the other the interoperable ISO861 form. – Panagiotis Kanavos Mar 28 '22 at 12:22
  • What datepicker are you using? `input type='date'`'s [value](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#value) is always in ISO8601 form, no matter the display format. – Panagiotis Kanavos Mar 28 '22 at 12:23
  • I'm using reactdatepicker.com and the custom input is just type="text" – ComCool Mar 28 '22 at 13:24
  • `react-datepicker` returns a Date object in local time. That's ... unfortunate when you only want the date. JavaScript doesn't have a date-only object though, and `YYYY-MM-DDT00:00:00` in one timezone may well represent a different date in another timezone. In JSON, dates are serialized as ISO8601 either in UTZ (Z suffix) or with a specific offset. The selected `Date` will be interpreted differently on each timezone. You could try telling `datepicker` to use `0` as the offset through the `utcOffset` parameter, to ensure the value isn't modified when serializing – Panagiotis Kanavos Mar 28 '22 at 13:36
  • Perhaps you should use the [Date.UTC](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC) function to create UTC dates from the datepicker value. If you check the Github repo you'll see this issue comes up over and over in different forms, eg [like this issue](https://github.com/Hacker0x01/react-datepicker/issues/1018). It also looks like [utcOffset doesn't work any more](https://github.com/Hacker0x01/react-datepicker/issues/1647). Requests to support different offsets are closed as won't fix – Panagiotis Kanavos Mar 28 '22 at 13:47

2 Answers2

0

This is known issue for react-datepicker.

You have 2 possible solutions -

  1. You can convert the date before sending data from the form, or
  2. You can convert it from UTC to Local and from Local to UTC for each date selection of the user.

You can see the the issue and code implementation of the 2nd solution here and here.

NBekelman
  • 13
  • 5
  • 3
    Not really a solution. The picker itself still is local time, so if you pick a day and time that falls within the offset, you're actually picking an entirely different day when you convert to UTC. e.g. You choose `2022-09-14T23:00:00.000-05:00` Converted it becomes `2022-09-15T04:00:00.000Z` So becomes somewhat of a mess if you're using date picker for filtering – colemars Sep 30 '22 at 20:54
0

I wanted to just completely disregard the user's local timezone, and not even use it for display or for sending to the API. In order to do that, I used their timezone just to parse dates back and forth from my target api timezone (utc). This is working for me:

it's in momentjs b/c our code is old, can replicate in newer libs

  const { timeZone: localTZ } = Intl.DateTimeFormat().resolvedOptions()
  // The TZ format I want everything to be displayed and submitted as
  const apiTZ = 'utc'
  const [apiTime, setApiTime] = useState(moment.utc())

  <DatePicker
    onChange={date => {
      const apiTimeFromPickerLocalDate = moment(date)
        .tz(localTZ)
        // change TZ without changing date/time
        .tz(apiTZ, true)
        .format()        
      setApiTime(apiTimeFromPickerLocalDate)
    }}
    selected={
      moment(apiTime)
        .tz(apiTZ)
        // Display picker time in local TZ without changing date/time
        .tz(localTZ, true)
        .toDate()
    }
  </DatePicker>

Playground Version (link)

const localDate = moment(new Date()).format();
const { timeZone: localTZ } = Intl.DateTimeFormat().resolvedOptions();
const apiTZ = "utc";
const apiTimeFromPickerLocalDate = moment(localDate)
  .tz(localTZ)
  // change TZ without changing date/time
  .tz(apiTZ, true)
  .format();

const pickerTimeFromApiTime = moment(apiTimeFromPickerLocalDate)
  .tz(apiTZ)
  .tz(localTZ, true)
  .toDate();

console.log("local time", localDate);
console.log("api time", apiTimeFromPickerLocalDate);
console.log("picker time", pickerTimeFromApiTime);
local time 2023-02-09T13:12:39-10:00 
api time 2023-02-09T13:12:39Z 
picker time Thu Feb 09 2023 13:12:39 GMT-1000 (Hawaii-Aleutian Standard Time)
Matt Wilde
  • 271
  • 2
  • 18