Skip to content

Commit

Permalink
[pickers] Add proper support for UTC and timezones (#8261)
Browse files Browse the repository at this point in the history
  • Loading branch information
flaviendelangle authored Jun 20, 2023
1 parent be1732e commit 13658f0
Show file tree
Hide file tree
Showing 201 changed files with 2,823 additions and 424 deletions.
71 changes: 0 additions & 71 deletions docs/data/date-pickers/adapters-locale/adapters-locale.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,74 +250,3 @@ This prop is available on all components that render a day calendar, including t
The example below adds a dot at the end of each day in the calendar header:

{{"demo": "CustomDayOfWeekFormat.js"}}

## Use UTC dates

### With dayjs

To use UTC dates with `dayjs`, you have to:

1. Extend `dayjs` with its `utc` plugin:

```tsx
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';

dayjs.extend(utc);
```

2. Pass `dayjs.utc` to `LocalizationProvider` `dateLibInstance` prop:

```tsx
<LocalizationProvider dateAdapter={AdapterDayjs} dateLibInstance={dayjs.utc}>
{children}
</LocalizationProvider>
```

3. Always pass dates created with `dayjs.utc`:

```tsx
<DateTimePicker
// ✅ Valid props
value={dayjs.utc()}
minDate={dayjs.utc().startOf('month')}
// ❌ Invalid props
value={dayjs()}
minDate={dayjs().startOf('month')}
/>
```

{{"demo": "UTCDayjs.js", "defaultCodeOpen": false}}

### With moment

To use UTC dates with `moment`, you have to:

1. Pass `moment.utc` to `LocalizationProvider` `dateLibInstance` prop:

```tsx
<LocalizationProvider dateAdapter={AdapterMoment} dateLibInstance={moment.utc}>
{children}
</LocalizationProvider>
```

2. Always pass dates created with `moment.utc`:

```tsx
<DateTimePicker
// ✅ Valid props
value={moment.utc()}
minDate={moment.utc().startOf('month')}
// ❌ Invalid props
value={moment()}
minDate={moment().startOf('month')}
/>
```

{{"demo": "UTCMoment.js", "defaultCodeOpen": false}}

### Other libraries

UTC support is an ongoing topic.

We will update the documentation with examples using other date libraries once the support for them will be sufficient.
38 changes: 38 additions & 0 deletions docs/data/date-pickers/timezone/BasicTimezoneProp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { TimePicker } from '@mui/x-date-pickers/TimePicker';

dayjs.extend(utc);
dayjs.extend(timezone);

export default function BasicTimezoneProp() {
const [value, setValue] = React.useState(dayjs.utc('2022-04-17T15:30'));

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<TimePicker
value={value}
onChange={setValue}
timezone="America/New_York"
label={'Rendered in "America/New_York"'}
/>
<TimePicker
value={value}
onChange={setValue}
timezone="Europe/Paris"
label={'Rendered in "Europe/Paris"'}
/>
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
40 changes: 40 additions & 0 deletions docs/data/date-pickers/timezone/BasicTimezoneProp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import dayjs, { Dayjs } from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { TimePicker } from '@mui/x-date-pickers/TimePicker';

dayjs.extend(utc);
dayjs.extend(timezone);

export default function BasicTimezoneProp() {
const [value, setValue] = React.useState<Dayjs | null>(
dayjs.utc('2022-04-17T15:30'),
);

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<TimePicker
value={value}
onChange={setValue}
timezone="America/New_York"
label={'Rendered in "America/New_York"'}
/>
<TimePicker
value={value}
onChange={setValue}
timezone="Europe/Paris"
label={'Rendered in "Europe/Paris"'}
/>
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
15 changes: 15 additions & 0 deletions docs/data/date-pickers/timezone/BasicTimezoneProp.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<TimePicker
value={value}
onChange={setValue}
timezone="America/New_York"
label={'Rendered in "America/New_York"'}
/>
<TimePicker
value={value}
onChange={setValue}
timezone="Europe/Paris"
label={'Rendered in "Europe/Paris"'}
/>
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
33 changes: 33 additions & 0 deletions docs/data/date-pickers/timezone/BasicValueProp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { TimePicker } from '@mui/x-date-pickers/TimePicker';

dayjs.extend(utc);
dayjs.extend(timezone);

export default function BasicValueProp() {
const [value, setValue] = React.useState(
dayjs.tz('2022-04-17T15:30', 'America/New_York'),
);

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<TimePicker
label={'Value timezone: "America/New_York"'}
value={value}
onChange={setValue}
/>
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
33 changes: 33 additions & 0 deletions docs/data/date-pickers/timezone/BasicValueProp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import dayjs, { Dayjs } from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { TimePicker } from '@mui/x-date-pickers/TimePicker';

dayjs.extend(utc);
dayjs.extend(timezone);

export default function BasicValueProp() {
const [value, setValue] = React.useState<Dayjs | null>(
dayjs.tz('2022-04-17T15:30', 'America/New_York'),
);

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<TimePicker
label={'Value timezone: "America/New_York"'}
value={value}
onChange={setValue}
/>
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
8 changes: 8 additions & 0 deletions docs/data/date-pickers/timezone/BasicValueProp.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<TimePicker
label={'Value timezone: "America/New_York"'}
value={value}
onChange={setValue}
/>
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
29 changes: 29 additions & 0 deletions docs/data/date-pickers/timezone/DayjsTimezone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';

dayjs.extend(utc);
dayjs.extend(timezone);

export default function DayjsTimezone() {
const [value, setValue] = React.useState(
dayjs.tz('2022-04-17T15:30', 'America/New_York'),
);

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<DateTimePicker value={value} onChange={setValue} />
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
29 changes: 29 additions & 0 deletions docs/data/date-pickers/timezone/DayjsTimezone.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';
import dayjs, { Dayjs } from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';

dayjs.extend(utc);
dayjs.extend(timezone);

export default function DayjsTimezone() {
const [value, setValue] = React.useState<Dayjs | null>(
dayjs.tz('2022-04-17T15:30', 'America/New_York'),
);

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<DateTimePicker value={value} onChange={setValue} />
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
4 changes: 4 additions & 0 deletions docs/data/date-pickers/timezone/DayjsTimezone.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<DateTimePicker value={value} onChange={setValue} />
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
25 changes: 25 additions & 0 deletions docs/data/date-pickers/timezone/DayjsUTC.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from 'react';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';

dayjs.extend(utc);

export default function DayjsUTC() {
const [value, setValue] = React.useState(dayjs.utc('2022-04-17T15:30'));

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<DateTimePicker value={value} onChange={setValue} />
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
27 changes: 27 additions & 0 deletions docs/data/date-pickers/timezone/DayjsUTC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as React from 'react';
import dayjs, { Dayjs } from 'dayjs';
import utc from 'dayjs/plugin/utc';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';

dayjs.extend(utc);

export default function DayjsUTC() {
const [value, setValue] = React.useState<Dayjs | null>(
dayjs.utc('2022-04-17T15:30'),
);

return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Stack spacing={2}>
<DateTimePicker value={value} onChange={setValue} />
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
</Stack>
</LocalizationProvider>
);
}
4 changes: 4 additions & 0 deletions docs/data/date-pickers/timezone/DayjsUTC.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<DateTimePicker value={value} onChange={setValue} />
<Typography>
Stored value: {value == null ? 'null' : value.format()}
</Typography>
Loading

0 comments on commit 13658f0

Please sign in to comment.