Reputation: 17
Breeze changes the timezone from +1:00 to 0:00. Value of my observable = 2013-11-11T00:00:00+01:00 and saveChanges()
sends back to server 2013-11-10T23:00:00.000+00:00. In my tables all dates are the previous day.
So far I've tried out all data types -> date
, datetime2
, datetimeoffset
. Breeze always sends back the date -1:00 hour. SQL Server 2008 R2, latest version of Breeze. The server is set to the correct timezone + 1:00.
Is there any way to send back set timezoneoff via saveChanges()
?
I've change the setting fpr newtonsoft like this:
JsonSerializerSettings customJsonSetting = new JsonSerializerSettings()
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
DateTimeZoneHandling = DateTimeZoneHandling.Local
};
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = customJsonSetting;
Still getting 1 hour minus. As I only need the Dates the timezone ist irrelevant for my application.
Thanks, Patrick
Upvotes: 1
Views: 1224
Reputation: 17052
Not sure I understand. Javascript internally stores all its dates as a number of milliseconds since January 1, 1970 00:00:00 UTC. Your browser then formats these dates into the browser's local timezone. But what gets sent to/from the server is always an ISO8601 serialization of the actual javascript date. This format allows for the representation of an 'exact' point in time. This point in time will be formatted differently depending on the timezone that it is formatted for, but the point in time itself does not change.
So, to clarify, Breeze does NOT change the dates in any way, except in the case of dates sent from the server without a timezone offset ( a different issue that has been discussed in other posts on this forum.). I'm not sure exactly what you are experiencing, but your comment about "The server is set to the correct timezone + 1:00.", is confusing to me. The timezone of the server is only relevant to the formatting of a date, not to its actual value.
However, Breeze does support several interception points both on the server and on the client.
On the server, if you are using ASP.NET WebApi or WebApi2 then you can create a custom implementation of the BreezeConfig class. BreezeConfig defines default behaviors; you can substitute your own behaviors by deriving from it and overriding its virtual methods. Breeze.NET will discover your subclass among the assemblies referenced by your project and use it instead of BreezeConfig.
To use BreezeConfig to configure the Json.Net serializer with specific settings. See http://james.newtonking.com/json/help/index.html. You can replace those settings by writing a subclass of BreezeConfig that overrides the 'CreateJsonSerializerSettings' method as shown in this example:
public class CustomBreezeConfig : Breeze.WebApi.BreezeConfig {
protected override JsonSerializerSettings CreateJsonSerializerSettings() {
var baseSettings = base.CreateJsonSerializerSettings();
// Default is DateTimeZoneHandling.RoundtripKind - you can change that here.
// baseSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
return baseSettings;
}
If you change this, then you will also likely need to replace Breeze's client side breeze.DataType.parseDateFromServer method. For example if you wanted to treat all dates serialized from the server as local you could do something like the following.
var _utcOffsetMs = (new Date()).getTimezoneOffset() * 60000;
// change to parse date as local
breeze.DataType.parseDateFromServer = function (source) {
var dt = breeze.DataType.parseDatesAsUTC(source);
if (breeze.core.isDate(dt)) {
dt = new Date(dt.getTime() + _utcOffsetMs);
}
return dt;
};
Please note that I am only explaining the customization points of breeze here. This is likely NOT the exact solution to your issue.
Upvotes: 3
Reputation: 721
In object initializer I use the following to keep all dates synced:
myObject.formattedMyTime = ko.computed({
read: function () {
return moment.utc(myObject.myTime()).format('DD/MM/YYYY HH:mm');
},
write: function (value) {
myObject.myTime(moment.utc(value).toDate());
}
});
Then I use only formattedMyTime
instead of myTime
. My software presumes only one time zone will be used so it doesn't really matter which one was actually used.
Upvotes: 1
Reputation: 127
I think the core of the issue is that Breeze.js uses toISODate to serialize the js Date. This causes the date to be sent to the server as the serialized value you're observing.
There is very little you can do to change this behaviour, at least I've not been able to find one. I suspect this is currently a hard constraint within breeze as per the documents:
Breeze on the client serializes per ISO 8601 and there is no supported way to change that behavior
Although ISO 8601 does support serializing dates with a +01 offset (for example), the behaviour of toISODate is to serialize the date as UTC Z (0 offset timezone).
There is a hack that I came up with that tries to fix up the UTC Z date in a BeforeSaveEntitiesDelegate but it really is crude and quite limited as the server has to make an imperfect guess as to whether Daylight saving time is being observed on the client and relies on a custom breeze Entity constructor to supply, as an unmapped value, the current timezone offset on the client.
The real solution will require an enhancement to breeze that adds an option to preserve timezone offset.
A request has already been made for the enhancement which you can vote up:
Christian
Upvotes: 0