Date picker: timezone shift

Viewed 17134

Problem

If I select a date in a <DateInput>, the datetime is in the user's timezone (e.g. 2017-07-01T00:00:00.000+02:00) but when it's sent to the server, it's transformed to UTC and thus ends up as 2017-06-30T22:00:00.000Z, one day behind.

The underlaying back-end is unaware of the user's timezone and cannot shift the dates back so after stripping the time it ends up with wrong date.

What would solve my problem

Any of these options would work fine:

  1. The datetime is sent with the user's timezone.
  2. The datetime is sent as naive (=without timezone).
  3. The date selected by the user is already treated as UTC.
  4. A date only (2017-07-01) instead of the ISO datetime is sent.

What I tried

  • I looked at Admin-on-rest's DateInput documentation and haven't found any option to alter the behaviour.
  • I looked at the related Material-UI's documentation and the only somewhat relevant option appears to be DateTimeFormat but despite a couple of tries I got nowhere.
  • I checked other answers, e.g Material UI Time Picker UTC but cannot figure out how to apply the suggested solution.
4 Answers

Well, since editing should not change author's intention and it's a bit too long for an edit I'm adding my own answer basing on tmt answer:

Option to use parse part is ok but function itself is faulty (see my comments in code to see why):

const dateString = v => {
  /* 
  * since v parameter coming is a string then you cannot use isNan 
  * undefined is also coming as a parameter so !v is good equivalent
  */
  if (!v) return; 

  let parsedDate = new Date(v);
  let adjustedDate = new Date(parsedDate.getTime() - parsedDate.getTimezoneOffset() * 60000);

  /*
  * since parameter coming in is a string you need to pass string further, that's why I added toISOString() call
  */
  return adjustedDate.toISOString();
};

<DateInput source="your_date" parse={dateString} />

Just set moment to specific timezone and intialize material ui picker with moment, and da da.. it will work..

import moment from 'moment-timezone';
import MomentUtils from '@date-io/moment';
import {DatePicker, MuiPickersUtilsProvider} from '@material-ui/pickers';

useEffect(()=>{
    moment.tz.setDefault('Asia/Kolkata');
},[])

<MuiPickersUtilsProvider libInstance={moment} utils={MomentUtils}>
               <DatePicker
                  variant='inline'
                  autoOk
                  label=''
                  disableToolbar
                  disableFuture
                  format='MM/DD/YYYY'
                  value={selectedDay}
                  onChange={(day) => {
                    const date = moment(day).format('MM/DD/YYYY');
                    setCurrentDay(date);
                    handleDayChange(day);
                  }}
                  InputProps={{
                    disableUnderline: true,
                    style: {
                      backgroundColor: 'white',
                      paddingLeft: 10,
                      borderRadius: 5,
                      width: 160,
                    },
                    endAdornment: (
                      <InputAdornment position='end'>
                        <CalendarTodayIcon style={{paddingRight: 8}} />
                      </InputAdornment>
                    ),
                  }}
                />
              </MuiPickersUtilsProvider>
Related