Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Datepicker popup UTC Timezone issue #6235

Open
msosa opened this issue Sep 13, 2016 · 18 comments
Open

Datepicker popup UTC Timezone issue #6235

msosa opened this issue Sep 13, 2016 · 18 comments

Comments

@msosa
Copy link

msosa commented Sep 13, 2016

Bug description:

I've noticed a weird issue when using the UTC timezone. For users west of UTC, like NY, adding the ng-model-options to UTC things work as they should.

However when you set your local timezone to something like UTC+2 and you open the popup that contains the ng-model-options, the date is highlighted incorrectly to the day before. The popup without the ng-model-options highlights the day correctly

Link to minimally-working plunker that reproduces the issue:

http://plnkr.co/edit/Y28iutmgkWkCINTUvRoq?p=preview

The first popup is the one without the ng model options, the second one contains it.

Version of Angular, UIBS, and Bootstrap

Angular:
1.5.8
UIBS:
2.1.3
Bootstrap:
3.3.6

@msosa
Copy link
Author

msosa commented Sep 13, 2016

Another thing I just noticed is if you select a date from the popup X amount of times where
X * (your offset) = more than 24 hours, on that click it will select the wrong date.

The offset seems to be constantly getting added and never zeroed out

@mark-mccullough
Copy link

+1

@antch
Copy link

antch commented Sep 21, 2016

Unfortunately there seems to be some issues with the timezone handling since 2.0.0 but your first post sounds like the same root cause as this issue that I just filed: #6252

Try setting your ng-model-options on a parent element of the input (instead of on the input itself), and see if that works.

@noullet
Copy link

noullet commented Oct 28, 2016

Hi,

I tried to track down the origin of this issue. It seems to come from

return dateParser.fromTimezone(date, ngModelOptions.timezone);

In UIBS 1.3.x the conversion was dateParser.toTimezone(...) and it is now dateParser.fromTimezone(...) in 2.2.0.

The date converted here was created by dateParser.parse, which used new Date(...)so the date uses the browser timezone. It makes no sense to read this date from the ngModelOptions timezone, but you probably want to convert it from the browser timezone to the ngModelOptions timezone.

Changing the line back to dateParser.toTimezone(...) does the trick for me.

It would be nice if someone from the UIBS team can look into this issue and review the workaround I suggest.

@wesleycho
Copy link
Contributor

@noullet this sounds correct - pushing change shortly.

@wesleycho wesleycho added this to the 2.3.1 milestone Nov 27, 2016
@msosa
Copy link
Author

msosa commented Dec 12, 2016

This did not seem to fix any of the two issues, am I doing something wrong? Here is new plunk with updated UIB code.

http://plnkr.co/edit/i2yg2cwHg7GC28Z7FhcC?p=preview

The date on the popup is still incorrect and clicking the date multiple times will still change the date.

@wesleycho
Copy link
Contributor

Reopening to investigate.

@noullet
Copy link

noullet commented Dec 12, 2016

I mistakenly believed that my issue had the same root as you @msosa, but it seems to be a third Timezone issue, independent from yours, sorry for the confusion...

@avainola
Copy link

avainola commented Jan 12, 2017

Seems that using ng-model-options="{timezone: 'utc'}" is not working with angular 1.6.x.
Could be cause by this breaking change in angular:

ngModelOptions:
Due to 296cfc, the programmatic API for ngModelOptions has changed. You must now read options via the ngModelController.$options.getOption(name) method, rather than accessing the option directly as a property of the ngModelContoller.$options object. One benefit of these changes, though, is that the ngModelControler.$options property is now guaranteed to be defined so there is no need to check before accessing.

This does not affect the usage in templates and only affects custom directives that might have been reading options for their own purposes. If you were programmatically accessing the options, you need to change your code as follows:

Before:
var myOption = ngModelController.$options && ngModelController.$options['my-option'];
After:
var myOption = ngModelController.$options.getOption('my-option');

@ksiwak2e
Copy link

ksiwak2e commented Jan 27, 2017

Yes this is problem after this change. I debug the problem on example of Bootstrap Datepicker version 2.3.1. In file ui-bootstrap-tpls in line 3044 they use
return dateParser.toTimezone(date, ngModelOptions.timezone)
but the timezone is undefined so the date is parse invalid. We will must use ngModelOptions.getOption('timezone').

But it can be also a problem for other libraries that use access to model options directly by object not by getter.

@antch
Copy link

antch commented Feb 24, 2017

I'm not sure if it's related to any or all of the issues presented here but there's still definitely an issue with the latest version (v2.5) and ngModelOptions.timezone. I set ng-model-options="{ timezone: 'UTC' }" on the uib-datepicker-popup (and on a parent element as well so that it propagates to the picker), and if I set my system time to 1am in a TZ just east of the UTC line, the dates do not sync up from the popup to the input box. The input box appears correct, whereas the popup does not let me select the current day.

@robert-iddink
Copy link

We also see problems with the datepicker popup in 2.5.0 (2.4.0 is fine, we're thinking that 0d79005 is the cause):

screen shot 2017-03-07 at 11 14 08

We have ng-model-options="{ timezone: 'UTC' }" on our body element and are using UTC Date objects in our application.

@sygnowskip
Copy link

We also have a similar problem with datepicker and UTC settings.

When we're in GMT -X, then the value set for ng-model is correct, but value displayed in text box is incorrect, is shifted by X (e.g. if we select 10-10-2000 and we're in GMT-5 timezone, then in text box we received 09-10-2000, because the date is shifted by -5 hours, ng-model contains correct value)

datepicker

@DakJack
Copy link

DakJack commented May 25, 2017

I'm also having a similar problem.

on Angular 1.6.1 UIBS 2.5.0

I have defined ng-model-options in various places trying to get this to work.
I have a desire to make all of my application show in UTC, so I configured that and it's working across all time zones.

The issue is if I set a time and move to another timezone then I have issues.

The first attachment is in the creation timezone
image

the second is in a timezone offset that screws it up
image

@dynshon
Copy link

dynshon commented Jun 6, 2017

I'm also having same @DakJack's problem, Angular 1.6.1 UIBS 2.5.0 and UIBS 2.4.0

My model come from Mysql, for example: 2017-06-23,

but I resolved parsing with uibDateParser.

$scope.dateTest = uibDateParser.parse($scope.dateTest , 'yyyy-MM-dd', new Date());

@kifirkin
Copy link

Any news here?

@kifirkin
Copy link

kifirkin commented Feb 16, 2018

I am using global datefilter decorator for setting timezone.
Also ng-model-options set to timezone: '+0300'.

If current local timezone differs from those above, datepicker active date doesnt work correct, cause it uses start and end of te day in local timezone

$provide.decorator('dateFilter', ['$delegate', '$injector', ($delegate, $injector) => {
    const delegate = $delegate;

    return function (date, format, timezone) {
        if (angular.isUndefined(timezone)) {
            timezone = '+0300';
        }

        return delegate.apply(this, [date, format, timezone]);
    };
}]);

@noullet
Copy link

noullet commented Apr 5, 2018

You'll find below how I found and solved my issues, hope this will help!

Problem
The popover version of uib-datepicker doesn't work well in combination with ng-model-options timezone in some timezones (e.g. negative timezones such as EST), including the highlight of "today", the minDate option...

My context

  • All dates come from my server in UTC, stored at midnight since I'm interested only in the year/month/hour part of the date. Btw, I strongly recommend doing that.
  • I use the UIB datepicker popover with ng-model-options="{timezone: 'utc'}"
  • I use angular 1.5.8 and UIB 2.2.0
  • My application is used by browsers all around the world, so any browser timezone should be supported.

Investigation
I decided to make it work. Thanks to #6671, I found out that the inline version seemed to work fine but not the popover, so I debugged the two.

The first step consisted in understand how the popover worked. For the inline version, the ng-model and the calendar are the same element, all managed by UibDatepickerController which directly accesses the model. For the popover version, it's different: the ng-model and the calendar are separated: the ng-model is managed by UibDatepickerPopupController, which "wraps" the inline version and its UibDatepickerController. In this case, the ng-model is not accessed directly by UibDatepickerController. UibDatepickerPopupController manages a local date variable in its scope to make the link between the ng-model and UibDatepickerController.

The first issue I found is that the ng-model-options are not passed in this process, so when using the inline version, UibDatepickerController uses the ng-model-options, while when using the popover version, UibDatepickerPopupController uses it but UibDatepickerController does not.

Fixing this is easy, great I'm done!

Actually, not so much... Indeed, I think the developers never got this "working" version, so they based their testing on erroneous premises. Thus, fixing the issue revealed all the code that did not take into account properly the conversion from and to the ng-model-options timezone.

Solution
I tried to track down all these conversion mistakes and fix them. Here is the resulting commit, with an attempt to explain every change, including the option passing and the conversions: icescrum/iceScrum@6b50b31#diff-27473a0b13f7d143a7153fb573f056c2

Disclaimer

  • Do not use my file as is, as it was already heavily customized before I commited that. I can't afford maintaining a fork that only adds these fixes to the latest UIB, but feel free to do that.
  • It fixes all my issues but I did not try using HTML5 date type, and I did not try the "today" button.
  • I am not sure this will work with angular 1.6 and UIB 2.5, but only minor adaptations should be required.

Let me know if it works for you!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests