Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

datepicker: min-date validation bug #11963

Closed
vdury opened this issue Jul 16, 2020 · 16 comments · Fixed by #12001 or #12002
Closed

datepicker: min-date validation bug #11963

vdury opened this issue Jul 16, 2020 · 16 comments · Fixed by #12001 or #12002
Assignees
Labels
has: Pull Request A PR has been created to address this issue i18n: localization This issue is related to internationalization P1: urgent Urgent issues that should be addressed in the next minor or patch release. resolution: fixed severity: regression This issue is related to a regression type: bug
Milestone

Comments

@vdury
Copy link

vdury commented Jul 16, 2020

Bug

In angular material 1.1.24, the datepicker directive sometimes invalidates a date if md-min-date is equal to selected date.

Demo and steps to reproduce the issue

Demo URL : https://material.angularjs.org/1.1.24/demo/datepicker#validations (Validations)

Detailed Reproduction Steps

  1. Today is 16/07/2020, md-min-date is set as 16/05/2020, and our timezone is GMT+4.
  2. Select in "Date-picker with min date and max date" demo calendar 16/05/2020 date.
  3. Date is valid.
  4. Repeat step 2 (reselect 16/05/2020)
  5. Date is invalid.

Explain the expected behavior

md-min-date is supposed to be inclusive, so we expect 16/05/2020 to be always valid on 16/07/2020.

List the affected versions of AngularJS, Material, OS, and browsers

  • AngularJS: 1.8.0
  • AngularJS Material: 1.1.24
  • OS: Windows
  • Browsers: Chrome

Add anything else we should know

We suspect method DateUtil.removeLocalTzAndReparseDate (introduced in commit) to be at the origin of the problem.

@Splaktar Splaktar changed the title datepicker min-date validation bug datepicker: min-date validation bug Jul 17, 2020
@Splaktar Splaktar self-assigned this Jul 17, 2020
@Splaktar Splaktar added the needs: feedback The issue creator or community need to respond to questions in this issue label Jul 17, 2020
@Splaktar
Copy link
Member

I am not able to reproduce this in a GMT-4 time zone at 6:30pm EDT.

I could try changing my computer's time zone in order to test this, but I need to know what the local time is for you when you are able to reproduce this?

@Splaktar
Copy link
Member

Oh and for step 4, is that really two steps combined? I.e. select some other valid date, then reselect the min date again?

@vdury
Copy link
Author

vdury commented Jul 20, 2020

The datepicker is malfunctioning on our personal app when local time is at midnight GMT+4.
On the angularJs demo page, at different times of the day (At 8:50am GMT+4 for example).
For step 4, you need to select the min date twice in a row. First time it's valid, and second time it's not.

@Splaktar
Copy link
Member

you need to select the min date twice in a row

This is what I'm not clear on. Are these the steps for this step 4?

4a. Select another date
4b. Select the min date again

However, I may be getting this wrong as it doesn't satisfy the "twice in a row" part of your description.

@vdury
Copy link
Author

vdury commented Jul 22, 2020

No I mean twice in a row as in :

  • I first select the min-date
  • I reopen the calendar
  • I reselect the min-date (even though it's already selected)
    datepicker-bug

This is on the demo page.
On our app, the datepicker is invalid at the init of the page. Local time is at midnight GMT+4. In the method DateUtil.removeLocalTzAndReparseDate, value.getTimezoneOffset() equals -240, so
dateValue = new Date(value.getTime() + 60000 * value.getTimezoneOffset());
decrements our date, which is then inferior to the min-date.

@Splaktar
Copy link
Member

OK, that helps a lot thank you! I wasn't sure that I was doing it right, since I can't reproduce it.

I think that we're going to have to change the calculation for all GMT+X timezones.

@Splaktar Splaktar added P1: urgent Urgent issues that should be addressed in the next minor or patch release. type: bug and removed needs: feedback The issue creator or community need to respond to questions in this issue labels Jul 22, 2020
@Splaktar Splaktar added this to the 1.2.0 milestone Jul 22, 2020
@Splaktar Splaktar added severity: regression This issue is related to a regression i18n: localization This issue is related to internationalization labels Jul 22, 2020
@berturion
Copy link

Hello, the 1.2.0 milestone seems a little big. As it is a regression from a fix done in the 1.1.24, in my opinion, it should be fixed in a 1.1.25 in order to finally have a 1.1 stable version. This issue is blocking the release of our product and we are not sure 1.2.0 will be stable enough because of its size. Can you please consider this possibility?

@Splaktar
Copy link
Member

Yes, I'll see about cherry picking this into a 1.1.25 release once we get it merged into master. Thank you for the feedback.

@Splaktar Splaktar modified the milestones: 1.2.0, 1.1.25 Jul 22, 2020
@Splaktar
Copy link
Member

As an update, I investigated this a bit after setting my laptop to GMT+4. However, I was not able to come up with an acceptable solution in the time that I had. Then I had to get re-focused on the 1.2.0 release and RCs due to some scheduling priorities.

I plan to revisit this after 1.2.0 final ships, with fixes being applied to both 1.2.1 and 1.1.25.

@berturion
Copy link

berturion commented Aug 24, 2020

Hi, I looked deeper into the code and found that the problem we have is located in the method DatePickerCtrl.prototype.onExternalChange.

At the very first load of the page, the value parameter is equal to Mon Aug 24 2020 00:00:00 GMT+0400 (heure de La Réunion)
Then, there this:

    if (this.dateUtil.isValidDate(value)) {
      this.date = this.dateUtil.removeLocalTzAndReparseDate(value);
    } else {
      this.date = value;
    }

As value is a valid date, this.date takes this.dateUtil.removeLocalTzAndReparseDate(value) resulting in Sun Aug 23 2020 00:00:00 GMT+0400 (heure de La Réunion), so it becomes yesterday.

This completely mess up the component. The view value is 24/08/2020, the internal value is 23/08/2020 and the minimum value is 24/08/2020 so that the component is in an invalid state, showing an error message but the date shown on the screen is good.

If I replace this piece of code by:

      this.date = value;

Our component is working as expected.
Though, I am not sure if this doesn't break the allow specifying timezone feature. as we don't use it at all.

@berturion
Copy link

berturion commented Aug 24, 2020

I don't understand the purpose of removeLocalTzAndReparseDate. I found an interesting page about converting dates to UTC here, if this was the goal:
https://praveenlobo.com/blog/how-to-convert-javascript-local-date-to-utc-and-utc-to-local-date/

@Splaktar
Copy link
Member

Hi, I looked deeper into the code and found that the problem we have is located in the method DatePickerCtrl.prototype.onExternalChange.

Thank you very much for looking into this.

I guess that I didn't explicitly state it above, but my previous investigation did identify that the approach used via removeLocalTzAndReparseDate() only works for GMT-X timezones and not for GMT+X timezones.

I am not sure if this doesn't break the allow specifying timezone feature.

The effect of this can be seen locally using the datepicker's Ng Model Options Timezone demo which uses ng-model-options="{timezone: 'UTC'}".
These examples below are given using a local timezone that is GMT-4:00.

With the existing code:
Screen Shot 2020-08-27 at 21 57 27
The date is properly set to midnight 6/19 in the UTC timezone for both the calendar and datepicker.

With removeLocalTzAndReparseDate removed from DatePickerCtrl.prototype.onExternalChange:
Screen Shot 2020-08-27 at 21 56 10
The date is properly set to midnight 6/19 in the UTC timezone for the calendar.
The datepicker dates are both 20 hours earlier than they should be in both timezones.

So yes, this breaks the support for specifying ng-model-options="{timezone: 'UTC'}" with UTC or another timezone when in a local GMT-X timezone.

@Splaktar
Copy link
Member

Now when testing locally with a GMT+3:00 timezone:

With the existing code:
Screen Shot 2020-08-28 at 05 09 45
The date is properly set to midnight 6/19 in the UTC timezone for both the calendar and datepicker.

With removeLocalTzAndReparseDate removed from DatePickerCtrl.prototype.onExternalChange:
Screen Shot 2020-08-28 at 05 09 22
The date is properly set to midnight 6/19 in the UTC timezone for the calendar.
The datepicker dates are both 3 hours earlier than they should be in both timezones.

@Splaktar
Copy link
Member

It appears that I can fix this by not doing the removeLocalTzAndReparseDate() call if ng-model-options isn't specified with a timezone setting:

    if (this.dateUtil.isValidDate(value) && timezone != null) {
      this.date = this.dateUtil.removeLocalTzAndReparseDate(value);
    } else {
      this.date = value;
    }

@Splaktar
Copy link
Member

Splaktar commented Aug 28, 2020

That however, does not fix an issue where the stand-alone calendar and calender in a datepicker, when a date is clicked on (in a GMT+X timezone when using ng-model-options="{timezone: 'UTC'}"), selects the previous date:

In this case, 6/19 is manually clicked upon in the stand-alone calendar and calender in the datepicker:
Screen Shot 2020-08-28 at 05 27 31

In a GMT-X timezone, this works fine:
Screen Shot 2020-08-27 at 22 29 08

But that appears to be a separate problem from this one, so I'll open a new issue.

Update: #12000 opened for this issue.

@Splaktar
Copy link
Member

Splaktar commented Sep 1, 2020

I don't understand the purpose of removeLocalTzAndReparseDate.

It supports custom date formatting with MomentJS (see #12006) in addition to fixing the date for GMT-X timezones when the date changes due to the timezone difference.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
has: Pull Request A PR has been created to address this issue i18n: localization This issue is related to internationalization P1: urgent Urgent issues that should be addressed in the next minor or patch release. resolution: fixed severity: regression This issue is related to a regression type: bug
Projects
None yet
3 participants