I'm trying to deserialize a JSON, which contains dates in the format 2017-10-26 13:32:11 Etc/GMT
. NodaTime seems to support this when combined with Json.NET and NodaTime.Serialization.JsonNet. I found some info here on StackOverflow that made me get this working, using only NodaTime:
var date = "2017-10-26 13:32:11 Etc/GMT";
var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
"yyyy'-'MM'-'dd HH':'mm':'ss z",
DateTimeZoneProviders.Tzdb
);
var result = pattern.Parse(date);
However when extending this example into deserializing a JSON using the other two packages, I can't get it to work. From reading documentation and other resources, I believe this is supposed to work:
public class DateObj
{
public ZonedDateTime Date { get; set; }
}
void Main()
{
var date = "2017-10-26 13:32:11 Etc/GMT";
var json = $"{{\"Date\": \"{date}\"}}";
var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
"yyyy-MM-dd HH:mm:ss z",
DateTimeZoneProviders.Serialization
);
var settings = new JsonSerializerSettings();
settings.ConfigureForNodaTime(pattern.ZoneProvider);
var dateObj = JsonConvert.DeserializeObject<DateObj>(json, settings);
}
But it throws an exception on the last line saying The value string does not match a quoted string in the pattern. Value being parsed: '2017-10-26^ 13:32:11 Etc/GMT'. (^ indicates error position.)
. What am I doing wrong?
Currently, you're creating a specific ZonedDateTime
pattern - but you're not actually telling Json.NET about that pattern anywhere.
If this is the only Noda Time type that you need to use, I'd advise that you don't call ConfigureForNodaTime
at all - because that will configure a ZonedDateTime
converter with the wrong pattern. We have code internal to NodaTime.Serialization.JsonNet to replace a converter, but that's not exposed at the moment. (Maybe we should do that...)
It's simple to just create a single converter though, and configure the settings for that:
var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
Converters = { new NodaPatternConverter<ZonedDateTime>(pattern) }
};
Here's what that looks like in the context of a full program. Note that I'm explicitly using DateTimeZoneProviders.Tzdb
here, rather than DateTimeZoneProviders.Serialization
, given that you definitely have TZDB identifiers:
using Newtonsoft.Json;
using NodaTime;
using NodaTime.Serialization.JsonNet;
using NodaTime.Text;
using System;
public class DateObj
{
public ZonedDateTime Date { get; set; }
}
class Program
{
static void Main()
{
var date = "2017-10-26 13:32:11 Etc/GMT";
var json = $"{{\"Date\": \"{date}\"}}";
var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
"yyyy-MM-dd HH:mm:ss z",
DateTimeZoneProviders.Tzdb
);
var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
Converters = { new NodaPatternConverter<ZonedDateTime>(pattern) }
};
var dateObj = JsonConvert.DeserializeObject<DateObj>(json, settings);
Console.WriteLine(dateObj.Date);
}
}
See more on this question at Stackoverflow