Search code examples
angulartypescriptdatepickerangular-materialutc

Angular material date picker: Date Parsing UTC problem 1 day before


I know there are several threads about this and i read them all but couldn't fix this for days. I might found a solution but it seems to be do dirty for me.

So as other users I have the same problem with the datePicker. For me it's the Angular Material Datepicker mat-datepicker

When I log the value I get the correct result:

Wed Dec 24 1999 00:00:00 GMT+0100 (Mitteleuropäische Normalzeit)

but in the request it is

1999-12-23T23:00:00.000Z

What I tried yet:

I've added { provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } } to my component and to my app.module.ts. That does not make any difference for me.

My dirty solution (before sending the request):

 let newDate= new Date(this.personalForm.get("dateOfBirth").value);
 newDate.setMinutes(newDate.getMinutes() - newDate.getTimezoneOffset());

When I am doing this the console logs:

Wed Dec 24 1999 01:00:00 GMT+0100 (Mitteleuropäische Normalzeit)

and the request is right:

1997-12-24T00:00:00.000Z

But if somebody now would be from a different timezone like GMT-0100 this would again not work. How to fix this correctly?

I also change the adapter dynamically if it's necessary to know:

 this._adapter.setLocale(this.translateService.currentLang);

Solution

  • The value which is picked and displayed is the same... it is the different formats of the date-time which show us a different result (where the date also changes)!!

    For e.g:

    • (by default): 2019-06-11T19:00:00.000Z
    • is equal to (by UTCString): Tue, 11 Jun 2019 19:00:00 GMT
    • is equal to (by LocaleString): 6/12/2019, 12:00:00 AM
    • is equal to (by LocaleTimeString): 12:00:00 AM

    We don't need to convert it, because the date object contains the same exact time.

    This stackblitz will further show the difference a format can make on the surface but the date is the same underneath; If you have questions/comments, you can fork this stackblitz, make changes and post a comment against this answer, i'll try to clarify.

    relevant TS:

    import {Component} from '@angular/core';
    
    /** @title Basic datepicker */
    @Component({
      selector: 'datepicker-overview-example',
      templateUrl: 'datepicker-overview-example.html',
      styleUrls: ['datepicker-overview-example.css'],
    })
    export class DatepickerOverviewExample {
      planModel: any = {start_time: new Date() };
      constructor(){}
    
      dateChanged(evt){
        let selectedDate = new Date(evt);
        console.log("by default:", selectedDate);
        console.log("by UTCString:", selectedDate.toUTCString());
        console.log("by LocaleString:", selectedDate.toLocaleString());
        console.log("by LocaleTimeString:", selectedDate.toLocaleTimeString());
      }
    
    }
    

    relevant HTML:

    <mat-form-field>
      <input matInput [matDatepicker]="picker" placeholder="Choose a date"
      [(ngModel)]="planModel.start_time"
      (ngModelChange)='dateChanged($event)'
      >
      <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker></mat-datepicker>
    </mat-form-field>
    
    <hr/>
    
    <p>By default: {{planModel.start_time}} </p>
    <p>Medium date: {{planModel.start_time | date:'medium'}} </p>
    <p>Short date: {{planModel.start_time | date:'short'}} </p>
    <p>Short time: {{planModel.start_time | date: 'shortTime' }} </p>
    <p>Medium time: {{planModel.start_time | date: 'mediumTime' }} </p>
    <p>Long time: {{planModel.start_time | date: 'longTime' }} </p>
    <p>Full time: {{planModel.start_time | date: 'fullTime' }} </p>