motss / app-datepicker

Datepicker element built with Google's lit and Material Design 2021
https://npm.im/app-datepicker
MIT License
180 stars 51 forks source link

datepicker went haywire before year 1983 is selected #88

Closed motss closed 7 years ago

motss commented 7 years ago

Description

Dates went haywire when any year before 1983 is selected. This could be related to the Date object implemented on the browsers and further investigation is needed to dive the issue down to figure the cause out. Otherwise, nothing can be done since it's a web platform issue.

Expected outcome

Dates should be computed as how dates are computed after year 1983.

Actual outcome

Dates went haywire when any year before 1983 is selected.

Live Demo

Steps to reproduce

Go to demo page and select any date before year 1983 in datepicker.

Browsers Affected

motss commented 7 years ago

@userquin Related to #87.

userquin commented 7 years ago

it seems you need to work with UTC: instead using new Date(y,m,d) you need to change it to Date.UTC(y,m,d)

userquin commented 7 years ago

new window.Intl.DateTimeFormat('es-ES', { day: 'numeric' }).format(new Date(1995,8,25)); "24" new window.Intl.DateTimeFormat('es-ES', { day: 'numeric' }).format(Date.UTC(1995,8,25)); "25"

userquin commented 7 years ago

It seems Intl accumulates offsets, I'm from Spain GMT+1 with DST (GMT+2 in summer time)

userquin commented 7 years ago

I have it working, you only have to change a few new Date to Date.UTC. I suggest you to include in the doc to use the string value to date datepicker value.

_readOnlyDate: will be the string used in:

   properties: {
      format: {
        type: String,
        value: function() {
          return 'yyyy/mm/dd';
         }
       },
       _readOnlyDate: String
   }
  <app-datepicker date="[[_readOnlyDate]]" format="[[format]]"...></app-datepicker>

If the returned value is to be shown, split the _readOnlyDate string with the separator supplied (in this case /) to build a Date for the client timezone and then use it to build a Date.UTC to print it:

var dateFromPicker = new Date(this._readOnlyDate.replace(/\//g, '-').split('-'));
var dateFromPickerString = new Intl.DateTimeFormat({day:'numeric',month:'short',year:'numeric'}).format(Date.UTC(
  dateFromPicker.getFullYear(), 
  dateFromPicker.getMonth(), 
  dateFromPicker.getDate()
);

I attach patch for latest version 2.10.1:

app-datepicker-2.10.1.patch.zip

motss commented 7 years ago

@userquin

This is confirmed. After changing my local machine's timezone to match yours and rewound the clock back to 11 hours ago, I was able to reproduce the issue.

By changing new Date to Date.UTC will likely solve the whole mystery. Would you like to submit a PR to fix this instead?

userquin commented 7 years ago

I have tested on windows 10 and android (chrome) and we also need to add timeZone: 'UTC' to DateTimeFormat options: data on screen must be consistent with their data. I'll check in all environments and then I'll try to make a PR as soon as posible...