I am using Couchbase Lite .Net in Xamarin and am trying to save dates and times while retaining the timezone information. To do this, I would like to use DateTimeOffset and not DateTime. This is because DateTime can only handle Local timezone or Utc, it has no concept of other timezones. In my testing, Couchbase seems to have no problem saving a DateTimeOffset property and the string in the Json that it saves has the correct string formatting, including timezone. For example:
2016-01-01T12:00:00-09:00
So saves appear to be working great. The issue is that when reading this property back in, CouchbaseLite will convert this property into a DateTime object. When it does this, the timezone gets changed to the local timezone and the time of day is adjusted accordingly. Although the tick count is the same as what was saved, I have now lost the timezone information.
To better illustrate the issue, I wrote some tests.
[Test]
public void CblSerializer_DateTimeOffset_RetainsTz(){
var mgr = Manager.SharedInstance;
using (var db = mgr.GetDatabase ("testdb")) {
Document doc = db.CreateDocument ();
string docid = doc.Id;
var expectedTime = new DateTimeOffset (2016, 01, 01, 12, 0, 0, new TimeSpan (-9, 0, 0));
var props = new Dictionary<string, object> {
{ "text", "This is text" },
{ "time", expectedTime }
};
doc.PutProperties (props);
Document resultDoc = db.GetDocument (docid);
//Test using Properties
object resultObj;
resultDoc.Properties.TryGetValue ("time", out resultObj);
Type propertyType = resultObj.GetType (); //The Type of the returned value is DateTime, not DateTimeOffset :(
Assert.That ((DateTimeOffset)resultObj, Is.EqualTo (expectedTime));
Assert.That (((DateTimeOffset)resultObj).Offset, Is.EqualTo (expectedTime.Offset));
//Test using GetProperty
var resultTime = resultDoc.GetProperty<DateTimeOffset> ("time"); //This fails and return a DateTimeOffset with zero ticks
Assert.That (resultTime, Is.EqualTo (expectedTime));
Assert.That (resultTime.Offset, Is.EqualTo (expectedTime.Offset));
}
}
In the test above, resultObj is a DateTime object with Kind = “Local” (which for me EST). This causes the timezone to get changed to -5:00 instead of -9:00 when it is cast to DateTimeOffset so my time ends up being
{1/1/2016 4:00:00 PM -05:00}.
The issue, I think, is that Couchbase Lite seems to handle all time formatted strings as DateTime and is deserializing them as such before I can get access to the property. Is there way I can change that behavior? Like substitute my own JsonSerializer for couchbase to use or directly access the raw json?
I know I could hack this by storing the DateTimeOffset as a string and add some helper functions in my data model to handle parsing it. But the example I am giving here is much simpler than the problem I am having in my real project so I cannot do that unfortunately. (I am using data models in a library which uses DateTimeOffset).