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

Datepicker popup timezone interpreted incorrectly #2072

Closed
dotcom9 opened this issue Apr 16, 2014 · 49 comments
Closed

Datepicker popup timezone interpreted incorrectly #2072

dotcom9 opened this issue Apr 16, 2014 · 49 comments

Comments

@dotcom9
Copy link

dotcom9 commented Apr 16, 2014

This may be related to #1031, but I'm not convinced it's exactly the same, so here's a fresh issue.

When you supply the datepicker popup with an ISO date with no timezone information, it interprets it as a UTC date, with the result that it displays the date incorrectly if the browser timezone is not also UTC.

For example, for a browser in EST (GMT-5) if the popup is given date "1980-03-03T00:00:00", the date displayed is 1980-03-02. Presumably it internally translates the supplied date into local time ("1980-03-02T19:00:00 EST").

As #1031 points out, an ISO date with no timezone information should be treated as a local date, so no adjustment should be made.

Although arguably this should be the default behaviour of the datepicker popup, I was hoping that as a workaround, I would be able to adjust the input using a custom formatter, in the same way that custom parsers are used to adjust the output value, However, when a custom formatter is applied, the popup behaviour is the same. Even though the formatter is called, It appears that the popup uses the raw model value rather than the formatted value.

This can be seen in this plunker; the formatter returns a random hard-coded date value ("01/01/1900") which is applied to the input element. Open the popup and see that the date has been set from the model value, ignoring the formatter. Set your browser PC to EST timezone and see that the popup is set to the day before the model value.

http://embed.plnkr.co/1r2i2IVKQVszXQ4IQXMl/preview

Is there any way the input value to the popup can be intercepted and modified to avoid this behaviour?

@jacqueslareau
Copy link

+1

1 similar comment
@bernhard-hofmann
Copy link

+1

@weberste
Copy link

I'm using a directive with a formatter and parser that works around the problem: https://gist.github.com/weberste/354a3f0a9ea58e0ea0de

Fundamentally, I believe it's not the datepicker that does the internal translation but the JavaScript Date (which the datepicker uses as a model).

@bikezilla
Copy link

+1
@weberste thanks for the gist - works perfectly!

@Squiggle
Copy link

Squiggle commented Aug 7, 2014

+1 for this.
Whilst it's not technically a bug (it works as specified), it doesn't work as most people would expect.
Would be great to have an option to force the datepicker to be backed by a UTC datetime instead of local datetime.

for example and if someone in Germany selects their birthday as 3rd June 1994 it becomes 1994-06-03T00:00Z and not 1993-06-02T23:00Z.
This would be incredibly useful, because the server often doesn't know the client's timezone if all dates are supplied UTC without offset, and it makes it very difficult to compensate after-the-fact.

Thanks!

@Zacharias3690
Copy link

+1
@weberste, @bikezilla
Trying to use this directive has the correct model time and the correct time in the input box, however the popup shows the previous day. Is there anything else you had to do to fix the problem?
Here's a plunkr demonstrating the issue: http://plnkr.co/edit/sFhA1LwfupvIK85eGPXp?p=preview
for reference I'm using central time

@StevenClontz
Copy link

I'm working with a JSON object sent by a Rails server which includes a Date rendered as 'yyyy-MM-dd' which has this same issue since Javascript first interprets the string as midnight UTC, then converts to my local time zone:

> new Date('2014-08-14')
Wed Aug 13 2014 19:00:00 GMT-0500 (CDT)

It would be very beneficial if we could either choose the timezone Datepicker uses, or if Datepicker could parse date strings like Angular's own date filter: angular/angular.js#1782

IgorMinar commented on Jan 9, 2013
previously we were always parsing the string input as UTC which cased issues like:

{{ '2012-04-01' | date:'d MMM yyyy' }} renders as 31 Mar 2012

BREAKING CHANGE: string input without timezone info is now parsed as local time/date

@prateem
Copy link

prateem commented Aug 20, 2014

+1

Should mention that this problem isn't only on the datepicker POPUP. It's with the datepicker in general.

@xavier-rodet
Copy link

+1
@weberste solution's is very very helpfull !!!!

@Zacharias3690 You need to use the directive with "datepicker-localdate" instead of "datepicker-local-date" (because the directive name is "datepickerLocaldate")

@stevebrowne
Copy link

@Zacharias3690 what worked for me (in GMT) was to change the second setMinutes calc to be minus not plus:

            // called with a 'yyyy-mm-dd' string to format
            ngModelController.$formatters.push(function (modelValue) {
                if (!modelValue) {
                    return undefined;
                }
                // date constructor will apply timezone deviations from UTC (i.e. if locale is behind UTC 'dt' will be one day behind)
                var dt = new Date(modelValue);
                // 'undo' the timezone offset again (so we end up on the original date again)
                dt.setMinutes(dt.getMinutes() - dt.getTimezoneOffset());
                return dt;
            });

This works for me as the timezone offset was a negative number, so - - == +

@Urigo
Copy link
Contributor

Urigo commented Oct 5, 2014

+1

5 similar comments
@cladera
Copy link

cladera commented Oct 8, 2014

+1

@dherik
Copy link

dherik commented Oct 15, 2014

+1

@lyadeski
Copy link

+1

@sricc
Copy link

sricc commented Oct 22, 2014

+1

@damianog
Copy link

+1

@chrisirhc chrisirhc added this to the Backlog milestone Nov 3, 2014
@starf
Copy link

starf commented Nov 4, 2014

Yes this please
+1

@HeIsHuaxi
Copy link

+1!!

@ThomDevine
Copy link

+1

2 similar comments
@benbartling
Copy link

+1

@JohnReagan
Copy link

+1

@benbartling
Copy link

Yea, I know about this guy 

-Ben

On Fri, Nov 14, 2014 at 3:17 PM, John Reagan [email protected]
wrote:

+1

Reply to this email directly or view it on GitHub:
#2072 (comment)

@chirkin
Copy link

chirkin commented Nov 17, 2014

+1

1 similar comment
@fmatosic
Copy link

+1

@bielmenezes
Copy link

Is the work around directive datepicker-localdate working fine for you all? I'm trying to use it but the date picker popup is still showing the incorrect day (one day before).

@damianog
Copy link

In my case (I am using asp.net + MVC + Json) I have added to the global configuration

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Local;

to solve the problem.

by what I I understood this behavior happened only with Chrome (not Firefox or IE) cause it's Standard adherence ?!

@bielmenezes
Copy link

I've change the directive 'datepickerLocaldate' to modificate the value direct in the model and now it is working properly. Both datepicker's dates in input field and popup are OK now.

directive('datepickerLocaldate', ['$parse', function ($parse) {
var directive = {
restrict: 'A',
require: ['ngModel'],
link: link
};
return directive;

    function link(scope, element, attr, ctrls) {
         var currValue = scope.$eval(attr.ngModel);

         if (currValue === undefined)
             return;

         //create a new date and set with the date from model
         var dt = new Date(currValue);

         //timezone adjustment
         dt.setMinutes(dt.getMinutes() + dt.getTimezoneOffset());

         var model = $parse(attr.ngModel);
         model.assign(scope, dt);
    }

}])

EDITED: this code does't works with IE/Firefox, like @damianog said, this is a Chrome specific behavior.. so, we will have to find another solution.. :(

@tagama
Copy link

tagama commented Nov 28, 2014

I took a look at the component's code and after seen this line:

var date = dateParser.parse(viewValue, dateFormat) || new Date(viewValue);

I realized that for some reason, the "dateFormat" that I was using was not correct so the result was "new Date(viewValue)". Correcting "dateFormat", "dateParser" handled correctly my date and timezone.

@cstefanache
Copy link

+1

@cumulate
Copy link

cumulate commented May 8, 2015

+1
@weberste you rock!!

@wilg
Copy link

wilg commented Jul 1, 2015

I worked around this by using a getterSetter with ng-model-options to perform the time zone conversions.

@skuepper
Copy link

I had the same problem, and found the easy solution here: http://stackoverflow.com/questions/27172394/javascript-doest-convert-angular-ui-datepicker-date-to-utc-correctly
Using the "cs-date-to-iso" directive together with the datepicker-popup corrects the wrong ng-value
and makes me happy :-)
HTH

@wesleycho
Copy link
Contributor

Looking at this further, what looks like is the root of this problem is that date.toJSON() is converting the date object into a string with the timezone shifted, which can result in a date shift.

This fork of the Plunker makes it clear - IMO, this particular issue is not a bug, but actually a subtle aspect of dates one must be careful about.

@icfantv
Copy link
Contributor

icfantv commented Feb 5, 2016

@eejai42, please do not only add a +1 to issues as it adds no intrinsic value to the discussion and serves to only clutter up the thread. Please read the last comment by @wesleycho as to why this will not be fixed.

I should also note that the datepicker now only accepts a JS Date object so the onus is on the API user to ensure their date is correct. If you require a rigid structure for your dates and date conversion you may use our $uibDateParser service (included in UIBS) or the absolutely fantastic third party library moment.js.

@eejai42
Copy link

eejai42 commented Feb 5, 2016

I have deleted my +1. I'm confused though. I understand the complexity of dates/time-zones/etc, but what I understood the original request to be (and the reason I added the +1) was that they wanted to be able to configure the datepicker to operate independently of timezone.

In other words, looking at the plunker - it shows the selected date as being March 2nd at 6:00 PM. If I change the timezone of my computer, it changes this date to March 2nd at 7:00 PM which is going to be the desired behavior MOST of the time, because 3/2 at 6:00 CST is the same as 3/2 at 7:00 EST, unless... it isn't.

In the app I'm working on right now for example, it keeps track of a class that is happening in a specific location. So the time of the class doesn't change based on where a user is, or what timezone they're in, but rather, the class will be taught at 5:00 PM in the timezone where the class is being taught. So it's confusing to my users to have it show that as 6:00 PM when they look at the class from a different timezone - because the class is still going to be at 5:00 (where it is being taught).

So what feels like it would be a good feature would be to have the date picker have an option to show the date as presented, rather than first converting it to a local time. Maybe I'm just misunderstanding wesleycho's comment - but it feel like are 2 different ways that the calendar could behave when presented with the date '2015-03-02'.

I agree that it isn't a bug, for sure - but it feels like there's room for an option to either have the date-picker convert to local time (or not) based on what is appropriate for the app. No?

@deeptinair17
Copy link

It still does not work for me :(

@djechelon
Copy link

Hi, I'd like to reopen this issue after hitting my head on it for several hours.

Long story short: my database saves the date picked up by the Date Picker one day before. I have investigated and concluded that it is a time zone issue.

Assuming that:

  • DatePicker control allows to select a date, regardless of the time
  • When you handle a date+time, the date depends on where you are in the world
  • If you handle a date only, you may not mind what time it is and where you are. A days covers 24 hours

Now after reading SO comment by Chris Lecher I have concluded that it could be a smart idea for Angular date picker to fix midday/noon as time of the day.

Daylight saving calculations are based on complex, constantly updating tables - and they do contain errors from time to time (maybe in this case only for your timezone?) They may also be different between Java and JavaScript. Since all of this can cause serious problems with DatePicker, the developers of GWT's built-in DataPicker chose to use the date at noon for safety (see the last few lines of com.google.gwt.user.datepicker.client.CalendarUtil) I assume, that "gwt-datepicker" doesn't?

Why?

Because there is a single moment in the time of the day when all the world's clocks tick the same day: midday at UTC. Actually the approach is the opposite: anywhere in the world, when the clock ticks 12:00PM you are sure that you are in the same UTC day.

This allows any server-side code to handle time zoning correctly with regards to date picking.

What do you think about it? I was thinking that GWT's barbatrick of setting 12:00PM was a coward workaround to cover a buggy implementation. Now that I think about it, while it's a workaround it's a genial idea with scientific basis!

If we wanted to go deeper in discussion I would point my finger to the fact that JS Date does not distinguish between a date (which is an interval) and a time (which is an instant in time at the maximum precision allowed by the standard: seconds)

@yuripramos
Copy link

+1
.
.
2 years passed and we are facing the same issue?
Trying to force +1 inside the library before return the utcDate but without success..

@florin-lei
Copy link

2018... issue not resolved

@tagama
Copy link

tagama commented Jul 10, 2018

Just use another lib

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