breezejs: date is not set to the right time
Asked Answered
S

2

10

I've noticed that if a date property comes back from the server with the value "2013-07-11T17:11:04.700", then breeze changes the value to Thu Jul 11 19:11:04 UTC+0200 2013.

Notice the time is now 2 hours ahead !

I had already come across this issue when saving entities, so I had to explicitly convert my date properties using momentjs :

 date.hours(date.hours() - moment().zone() / 60);

But now it seems the problem occurs also when doing read operations.

What's the best way to make sure breeze does not alter values of my date properties ?

Sheliasheline answered 15/7, 2013 at 15:5 Comment(0)
S
19

Breeze does not manipulate the datetimes going to and from the server in any way EXCEPT to add a UTZ timezone specifier to any dates returned from the server that do not already have one. This is only done because different browsers interpret dates without a timezone specifier differently and we want consistency between browsers.

The source of your issues is likely to be that when you save your data with dates to the database, that the dateTime datatype you are using does NOT contain a timezone offset. This means that when the data is retrieved you are likely "losing" the offset and the Breeze default mentioned above kicks in. This can be corrected by using a database date time datatype with an timezone offset ( datetime2 or datetimeoffset in SQLServer).

Note that your browser DOES format dates according to it's current timezone.

Another approach is that you can replace Breeze's DataType.parseDateFromServer to NOT infer any time zone info if it is not provided:

breeze.DataType.parseDateFromServer = function (source) {
     return new Date(Date.parse(source));
};

However, this can run into the problem that different browsers interpret DateTime strings without a time zone offset differently... So you may still get strange results depending on the browser. If that happens you will need to add some browser detection code to the snippet above.

Another alternative is to do the following using the moment.js library.

breeze.DataType.parseDateFromServer = function (source) {
     var date = moment(source); 
     return date.toDate();   
};

Not sure how helpful this is, but hopefully Breeze's behavior is clearer.

Selector answered 16/7, 2013 at 6:28 Comment(5)
Jay: I have tried to implement the above when i print to the console the source and output i get: 2015-11-08T12:30:00.000Z-> 2015-11-08T12:30:00+00:00. I am using moment library in the following way: moment.utc(source).format();. However later on when i query the entity which is filled with data, it seems to put in back to the local timezone. Is this the expected behavior? The entity is storing: GMT+0200 (South Africa Standard Time).Indolence
Sorry one more thing to add - the time is naturally incorrect as it then has a 2 hour difference in it.Indolence
best part of 7 hours debugging breezejs's date comparison code to finally find that the issue was because Safari cant handle 2017-02-12 21:00:00.000Z as a date and Breezejs silently converted Invalid Date to null, used the momentjs solution to fixNosing
Do you have to change this in the breeze code itself or is there a hook to override somewhere globally?Blacksnake
and what about going from client back to server...want the date to go as is...no timezone..Blacksnake
S
0

By default, Breeze does not provide any way to do this, but you can keep the below code in your model JS file to overcome this issue:

breeze.DataType.parseDateFromServer = function (source) {
                if (typeof source === 'string') {
                    //Check for local offset time or UTC time from server
                    if (source.slice(-1) !== "Z") {
                        var oldSource = source;

                        try {
                            source = source.substring(0, source.lastIndexOf("-") - 1)
                            source = new Date(source);
                            var tzDifference = source.getTimezoneOffset();
                            //convert the offset to milliseconds, add to targetTime, and make a new Date
                            var offsetTime = new Date(source.getTime() + tzDifference * 60 * 1000);
                            return offsetTime;
                        }
                        catch (err) {
                            source = new Date(source);
                            return source;
                        }
                    }
                    else {
                        source = new Date(source);

                        var tzDifference = source.getTimezoneOffset();
                        //convert the offset to milliseconds, add to targetTime, and make a new Date
                        var offsetTime = new Date(source.getTime() + tzDifference * 60 * 1000);

                        return offsetTime;
                    }
                }
            }
Staceystaci answered 3/1, 2017 at 15:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.