Material-ui-pickers: Trying to Present in UTC, and Save in UTC. Cannot get data without timezone conversion

Created on 5 Apr 2018  路  14Comments  路  Source: mui-org/material-ui-pickers

Environment

| Tech | Version |
|---------------------|---------|
| material-ui-pickers | 1.0.0-rc.4 |
| material-ui | 1.0.0-beta.33 |
| React | 16.2.0 |
| Browser | Chrome |
| Platform | |

Steps to reproduce

  1. Date & Time Picker Basic Example

Expected behavior

Component to send me back either:
A) Format like so: 2018-04-04T13:48:00.000Z
B) Accept my UTC=true flag, and NOT apply a timezone conversion as it is here: Fri Apr 20 2018 10:28:00 GMT-0700 (PDT)

Actual behavior

i) I can only receive the 2018-04-04T13:48:00.000Z format when I wrongly send a default value date string yyyy-mm-dd. This comes through as {}._i when the component submits. As soon as I send the proper selectedValue through, the {}._I property becomes Fri Apr 20 2018 10:28:00 GMT-0700 (PDT).
ii) Am am applying UTC=true to the component. I can see _isUTC as true in the submission object. But the datetime format is still having the PDT conversion applied.

import React from 'react';
import moment from 'moment-timezone';
import MomentUtils from 'material-ui-pickers/utils/moment-utils';
import MuiPickersUtilsProvider from 'material-ui-pickers/utils/MuiPickersUtilsProvider';
import { DateTimePicker } from 'material-ui-pickers';

moment.tz.setDefault('UTC');

function DateAndTimePicker(props) {
  const { handleChange, label, selectedDate } = props;

  return (
    <MuiPickersUtilsProvider
      moment={ moment }
      utils={ MomentUtils } >
      <DateTimePicker
        disablePast
        label={ label }
        onChange={ handleChange }
        value={ selectedDate }
      />
    </MuiPickersUtilsProvider>
  );
}


export default DateAndTimePicker;

Most helpful comment

I think he's wanting the date to display in UTC instead of the local timezone, as the two expected behaviours listed are both in UTC. Is this possible?

All 14 comments

I am not fully sure what you want. Inside pickers would call moment(value) and if you are passing flag Z it says that you are passing in UTC and everything works fine for me => value returns in that timezone, you mentioned in the string or it would be taken from default.

I think he's wanting the date to display in UTC instead of the local timezone, as the two expected behaviours listed are both in UTC. Is this possible?

Yes, it's possible.

you need to create you own Utils class to handle the format:

class UTCUtils extends MomentUtils {
  format(value, formatString) {
    return moment(value)
      .utc()
      .format(formatString);
  }
}

export default class extends Component {
  render() {
    return (
      <MuiPickersUtilsProvider utils={UTCUtils} moment={moment}>
         <App />
   ...

and you also need to handle the date in the handleChange(date) function:

handleChange = (dateValue) => this.setState({
  selectedDate: moment.utc(dateValue.format('YYYY-MM-DD HH:mm:ss')),
})

This doesn't seem to fully work. While the text box preserved the UTC date, if you edit the date, the date picker control reverts back to using the local timezone.

You need to pass also moment instance to the Utils provider

Yes, got it working. Thank you.

I am trying to implement exactly this. The input box works as expected, but not the actual TimePicker

I have moment with Europe/London as default timezone and I am currently in Europe/Madrid timezone (+01:00) and this is what I see:

Screenshot 2019-08-28 at 18 23 22

The time at the top looks fine, but the hour picker is in my local timezone.

What about an example with luxor library ?

Same problem as @guilleironhack

Could you do this?

class UTCUtils extends MomentUtils {
    date(value) {
        let theDate = super.date(value);
        return theDate.utc();
    }
}

@stephan-king what is your final UTCUtils file?

Has anyone been able to solve the problem @guilleironhack is having above?

I'm no longer using the time picker, but I solved my UTC timezone issues by passing as libInstance a moment-timezone instance configured as follows:

import moment from 'moment-timezone';
moment.tz.setDefault('Etc/UTC');

this is my working solution

import MomentUtils from '@date-io/moment';

class MomentUTCUtils extends MomentUtils {
  format(value, formatString) {
    return this.moment.utc(value).format(formatString);
  }

  parse(value: string, format: string) {
    if (value === '') {
      return null;
    }

    return this.moment.utc(value, format, true);
  }

  date(value?: any) {
    if (value === null) {
      return null;
    }

    const moment = this.moment.utc(value);
    moment.locale(this.locale);

    return moment;
  }
}

export default MomentUTCUtils;
import React from 'react';

import { MuiPickersUtilsProvider } from '@material-ui/pickers';
import moment from 'moment';

import MomentUTCUtils from './MomentUTCUtils';

type Props = {
  children: React.ReactNode;
};
export const UTCWrapper = ({ children }: Props) => {
  return (
    <MuiPickersUtilsProvider utils={MomentUTCUtils} locale={'pt-br'} moment={moment}>
      {children}
    </MuiPickersUtilsProvider>
  );
};

usage:

<UTCWrapper>
   <DatePicker />
</UTCWrapper>

Using this could cause more harm then good

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Harasz picture Harasz  路  3Comments

harvitronix picture harvitronix  路  3Comments

dandv picture dandv  路  3Comments

aditya81070 picture aditya81070  路  3Comments

brett-patterson picture brett-patterson  路  3Comments