components: Day incorrect in datepicker

Bug, feature request, or proposal:

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

here’s the code: <md-form-field> <input mdInput [(ngModel)]="fareCalendar.startDate" name="startDate" [mdDatepicker]="picker" placeholder="startDate"> <md-datepicker-toggle mdSuffix [for]="picker"></md-datepicker-toggle> <md-datepicker #picker></md-datepicker> </md-form-field>

I am using angular 4 and @angular/material": "^2.0.0-beta.10 rtcnm

but the date: f5z10

How can I send the UTC date

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 22
  • Comments: 46 (19 by maintainers)

Commits related to this issue

Most upvoted comments

@mmalerba shouldnt the datepicker not support timezones

its for selecting only date

if i am selecting date of birthday it shouldnt change according to different time zones

I made my self a workaround by overriding the MomentJS DateAdapter compiling the date from UTC and then converting it into the locale date:

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;
  }
}

The important line being:

let result = moment.utc({ year, month, date }).locale(this.locale);

You can change the default behaviour to parse dates as UTC by providing the MAT_MOMENT_DATA_ADAPTER_OPTIONS and setting it to useUtc: true.

@NgModule({ imports: [MatDatepickerModule, MatMomentDateModule], providers: [ { provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } } ] })

Check here for more details

I get this exact same behaviour on https://material.angular.io/components/datepicker/overview It always adds +1 day after selected.

Maybe the problem here is the fact that the datepicker’s value is a Date in the first place. Date is a perfectly good(ish) class for representing an absolute instant in real time; it’s a terrible representation of a calendar date. This entire thread, dozens of posts, dozens of users complaining, could have been avoided if the default date adapter went to/from ISO 8601 date-only strings. Every date library (and of course the native Date object) understands them, they are exactly as specific as the UI that generated them, and they can be “upgraded” to an instant or range of real time by simply adding “Z” on the end. What I mean to say is, adding context to go from “2018/11/26” to “2018/11/26Z” makes sense, but going the other way – trying to remove time-zone-ness from the data – does not.

Of course, I can fix all this by writing my own date adapter, or going out and getting the Moment-based one, but as long as the default behavior is Date-based, you’re going to keep seeing people showing up in this thread.

Why does datepicker care about the timezones at all? Who would ever need that?

I’m also getting a incorrect date.

bug-on-datetime

We do plan to add support for different timezones/offsets, but its not there yet. In the mean time you could make a custom DateAdapter that works with UTC dates to accomplish this.

Here is the DateAdapter class you would have to extend: https://github.com/angular/material2/blob/master/src/lib/core/datetime/date-adapter.ts

Some examples of existing implementations: https://github.com/angular/material2/blob/master/src/lib/core/datetime/native-date-adapter.ts https://github.com/angular/material2/blob/master/src/material-moment-adapter/adapter/moment-date-adapter.ts

And some documentation that may help: https://material.angular.io/components/datepicker/overview https://blog.angular.io/taking-advantage-of-the-angular-material-datepicker-237e80fa14b3

@raibait, in fact, it doesn’t care about it. But the underlying objects that currently store the date values usually do (regular javascript Date objects and Moment.js are the most common cases). This is the reason for so many issues related to wrong dates. Building a date adapter and configuring it correctly is important to avoid headaches.

Silthus’ workaround works great.

@mmalerba: Is there a plan to implement something into oficial MomentDateAdapter to avoid workarounds?

Indeed it should, hence the open PR to fix it

@julianobrasil it looks like that article you linked is spot on. IE seems to be doing its own DST correction, so my logic to do it manually with UTC dates is overcompensating

Oddly enough, this started happening when the Aussie daylight savings time ticked over.

Strange because he same problem doesn’t happen here in Europe. Then again, maybe it will when the clocks change at the end of the month.

@mmalerba same issue on the docs, see: bug-on-angular-datepicker

I’m using MdNativeDateModule on my application.

Oh, you may be refering to the fact that the UTC time add/subtract your current time offset. Look at the picture below: I’m in a GMT+2h00 zone, so, my UTC value is offset by 2 hours. So, if I set the hours to 23h00 in my Date object, my UTC date get offset to the day after (as in 1h00 am).

image