Angular DatePicker stuff: date becomes one day before selected date
I am using the latest Angular 4 and Angular-Material2-2.0.0-beta7. This is my template using MdDatePicker
:
<md-input-container fxFlex="33" class="birthday-container">
<input mdInput name="birthday" placeholder="Birthday" required [(ngModel)]="member.birthday" [mdDatepicker]="birthdayPicker">
<button mdSuffix [mdDatepickerToggle]="birthdayPicker"></button>
</md-input-container>
<md-datepicker #birthdayPicker></md-datepicker>
In app.module, here is the provider:
{provide: DateAdapter, useClass: NativeDateAdapter}
And member.birthday
there is Date
. But when JSON.stringify(member.birthday)
, it becomes one day before the selected date. For example:
Select the 2017-4-1
date in the picker and the string result is 2017-03-31T13:00:00.000Z
.
This post raised the same question, but I'm not sure how to apply moment.js
to code.
source to share
When we select a date in the date picker, the selection is saved and processed in GMT (Greenwich timezone), but displayed back to the user in a formatted view based on the user's current time zone. Therefore, the stored and displayed dates are different (except for users in the +0 time zone, such as Greenwich).
When formatting a JS Date object, we get a clear Greenwich Mean Time, we can see it at https://time.is/GMT . What you probably expect to see is a time representation formatted with your current time zone. See the difference in my example.
// get current time
let date = new Date();
console.log('NATIVE JS DATE TIME', date.toString());
console.log('STRINGIFIED TIME', JSON.stringify(date));
console.log('FORMATTED TIME', `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`);
you can use a very convenient moment format()
to display the date.
source to share
I solved this problem by creating a custom date adapter (which inherits its own date adapter) and overriding the create-date method to remove the timezone offset
@Injectable({ providedIn: 'root' })
export class CustomDateAdapterService extends NativeDateAdapter {
public createDate(year: number, month: number, date: number): Date {
const localDate = super.createDate(year, month, date);
const offset = localDate.getTimezoneOffset() * 60000;
return new Date(localDate.getTime() - offset); // utcDate
}
}
you can take a look at the full gist here
source to share