When I select a date I see the correct date in the field but, when I save, the datepicker send the day before the date I have selected ( 3 hours offset ) i am using angular
Two days ago, at https://github.com/angular/material2/issues/7167, Silthus posted his workaround that overrides the MomentJsDataAdapter. I tried it and it worked as a charm from anywhere in the globe.
First he added a MomentUtcDateAdapter that extends MomentDateAdapter
import { Inject, Injectable, Optional } from '@angular/core';
import { MAT_DATE_LOCALE } from '@angular/material';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
import { Moment } from 'moment';
import * as moment from 'moment';
@Injectable()
export class MomentUtcDateAdapter extends MomentDateAdapter {
constructor(@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string) {
super(dateLocale);
}
createDate(year: number, month: number, date: number): Moment {
// Moment.js will create an invalid date if any of the components are out of bounds, but we
// explicitly check each case so we can throw more descriptive errors.
if (month < 0 || month > 11) {
throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`);
}
if (date < 1) {
throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
}
let result = moment.utc({ year, month, date }).locale(this.locale);
// If the result isn't valid, the date must have been out of bounds for this month.
if (!result.isValid()) {
throw Error(`Invalid date "${date}" for month with index "${month}".`);
}
return result;
}
}
And then in the AppModule component, you have to do this:
providers: [
...
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
{ provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
{ provide: DateAdapter, useClass: MomentUtcDateAdapter },
...
],
The solution stackblitz works great, but if you are not storing the timestamp in Database, then you need to convert back the date to UTC format while retrieving it from database before assigning to the datepicker.
let dbDate = new Date('2018-02-09T00:00:00.000Z');
let updateDate = new Date(
Date.UTC(dbDate.getFullYear(), dbDate.getMonth(), dbDate.getDate())
).toISOString(); // 2018-02-08T00:00:00.000Z
now assign the updatedDate
to the datepicker, hope this helps.
Angular material date picker does not support different time zones at the moment and it gives you an UTC time offset. But to me it is not a problem as i save the output string to my database and when i return it back to user the browser shows the correct date time object. Try this in your console(im in +01 zone) and you will see the selected date:
new Date('2018-02-08T23:00:00.000Z')
Fri Feb 09 2018 00:00:00 GMT+0100 (CET)
Another solution is to modify your date object before saving to database which is not the best practice.
Lastly, If you are using Moment.js in your app you could give the MomentDateAdapter
a try and see if it helps you. Just add the MatMomentDateModule
to your application as described here.