Material UI DatePicker Showing Wrong Date
Asked Answered
U

4

24

The displayed date in Material UI Pickers is 1 day behind the selected date:

I selected 25th, the value in formik is 25th but the value displayed on the form is 24th.

  "@date-io/date-fns": "^1.3.13",
  "date-fns": "^2.9.0",
import DateFnsUtils from '@date-io/date-fns';
import { MuiPickersUtilsProvider, DatePicker } from '@material-ui/pickers';
import { format, addDays } from 'date-fns';

<MuiPickersUtilsProvider utils={DateFnsUtils}>
    <FastField
       as={DatePicker}
       variant="inline"
       disableToolbar
       name="startTime"
       format="PPP"
       onChange={date => {
         console.log(format(date, 'yyyy-MM-dd'));
         setFieldValue('startTime', format(date, 'yyyy-MM-dd'));
       }}
       value={values.startTime}
   />
</MuiPickersUtilsProvider>

enter image description here

Ulrick answered 24/2, 2020 at 18:39 Comment(7)
I think it might be related to time zone differences. Look at the first example here: date-fns.org/docs/Getting-Started#introduction The function is format(new Date(2014, 1, 11), 'MM/dd/yyyy'), but the result is '02/11/2014'. Try playing with the api of this library(i recommend moment.js...)Naissant
What am i looking for in the first example, I don't see anythingUlrick
I've updated my commentNaissant
I tried to do something like this to address timezone maybe: format(endOfDay(new Date(date)), 'yyyy-MM-dd') but no changeUlrick
date-fns.org/v2.0.0-alpha.27/docs/Time-Zones try looking here, i think you might find the solution. i belive it's timezone related.Naissant
Just make sure it's the correct version..i aint sure about the link i sent youNaissant
I had the same issue, moved to moment and solved the issue for me. import MomentUtils from '@date-io/moment'; ref: material-ui-pickers.dev/getting-started/installationOllieollis
S
17

I've faced the same problem

After all, I added a parseISO method on my date, you need to specify the timezone of the component.

// import parseISO
import { parseISO } from 'date-fns'; 

On value (property which is date)

<KeyboardDatePicker
  format={'dd/MM/yyyy'}
  label="Date"
  value={parseISO(salesPage.dateAt)}
  onChange={handleDateAtOnChange}
/>

On change


import { format } from 'date-fns';
import { convertToLocalTime } from 'date-fns-timezone';


export const DEFAULT_DATE_FORMAT = 'yyyy-MM-dd';

/**
 * Format a date to a string
 *
 * @param date
 */
export const formatDate = (date) => {
  if (!date) return new Date().toLocaleString();

  // Get the timezone from browser using native methods
  const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
  const dateTmp = Date.parse(date.toLocaleString());

  const localDate = convertToLocalTime(dateTmp, {
    timeZone: timezone,
  });

  return format(localDate, DEFAULT_DATE_FORMAT);
};

const handleDateAtOnChange = (event) => {
  formatDate(event.target.value)
}


Skirmish answered 12/11, 2020 at 14:21 Comment(3)
The parseISO package is what it was missing for me. Thanks for sharing this tipOliverolivera
What is DateFormatEnum?Bogosian
The format of the date you want. ` export enum DateFormatEnum { YearMonthDay = 'yyyy-MM-dd', DayMonthYearPtBr = 'dd/MM/yyyy', } `Glossitis
J
6

its because datepicker takes input date-time in UTC ISOformat Solution - Convert UTC to local to ISO format

because server only accepts ISO date-time so I converted UTC to local timezone and sent it to server in ISO format

declare this somewhere

function convertUTCDateToLocalDate(date) {
    var newDate = new Date(date.getTime() - date.getTimezoneOffset()*60*1000);
    return newDate;   
}

and do this where you need local datetime in ISO format convertUTCDateToLocalDate(date).toISOString()

Jackfish answered 24/10, 2021 at 20:57 Comment(1)
it works for me, but instead of - I used +.Abagael
P
0
  • You can make use of moment lib method .utcOffset() and get this functionality to work.
  • Make sure that the state is controlled and if you are fetching the data, remember to use the same method to format it again

const handleDateAtOnChange = (e) => {
const date = moment(e.target.value).utcOffset(0, false).format("MM-DD-YYYY")
setDate(date)
}

<DatePicker 
value={date} 
onChange={handleDateAtOnChange}
format="MM/dd/yyyy"
/>

Pollak answered 27/6, 2022 at 12:47 Comment(1)
Hey! I've been trying to make work the code but the .utcOffset(0, false) does not solve the problemContrabandist
B
0

I fixed this easily with "string concatenation".

In the .component.html

<mat-form-field>
  <input matInput readonly [matDatepicker]="picker" placeholder="Date of birth" formControlName="dob" (dateChange)="formatDate($event)">
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
  <mat-error *ngIf="handleError('dob', 'required')">Date of birth is required</mat-error>
</mat-form-field>

In the .component.ts

/* format date */
formatDate(e: any) {
  var d = new Date(e.target.value)
  var convertDate = d.toISOString().substring(0, 10) + d.toISOString().substring(10,);
  this.actorForm.get('dob')?.setValue(convertDate, { onlyself: true });
}

See my answer to this case at https://mcmap.net/q/583488/-angular-material-datepicker-shows-one-day-behind-in-angular-9-when-i-click-search-button

Brianbriana answered 3/8, 2022 at 2:5 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.