C# json.net日期时间的序列化/反序列化';未指定';

C# json.net日期时间的序列化/反序列化';未指定';,c#,datetime,serialization,timezone,json.net,C#,Datetime,Serialization,Timezone,Json.net,在常规的.net中, 如果我们的时间有DateTimeKind.未指定 如果我们将其转换为本地,则转换时假定输入日期为UTC。 如果我们将其转换为通用,则在转换时它假定输入日期是本地的 然而,在JSON.Net中,如果JSON.Net中的字符串日期未指定,它似乎没有这种逻辑?看看下面我的测试用例——我做错什么了吗?还是这是故意的?还是JSON.Net中的错误? 谢谢 //TODO:输出失败 //日期字符串:“2014-06-02T21:00:00.0000000” //序列化日期:2014-06

在常规的.net中, 如果我们的时间有DateTimeKind.未指定 如果我们将其转换为本地,则转换时假定输入日期为UTC。 如果我们将其转换为通用,则在转换时它假定输入日期是本地的

然而,在JSON.Net中,如果JSON.Net中的字符串日期未指定,它似乎没有这种逻辑?看看下面我的测试用例——我做错什么了吗?还是这是故意的?还是JSON.Net中的错误? 谢谢

//TODO:输出失败
//日期字符串:“2014-06-02T21:00:00.0000000”
//序列化日期:2014-06-02T21:00:00.0000000Z
//预期的日期和时间,但未找到。
[测试方法]
public void NEW_应将未指定的日期字符串反序列化为utc日期()
{
string dateString=“\”2014-06-02T21:00:00.0000000\”;
DateTime dateRaw=新的DateTime(2014,6,2,21,0,0,0,DateTimeKind.未指定);
DateTime dateRawAsUtc=新的日期时间(2014,6,3,4,0,0,0,DateTimeKind.Utc);
dateRawAsUtc.Should().Be(dateRaw.ToUniversalTime());
JsonSerializerSettings设置=新建JsonSerializerSettings();
settings.DateTimeZoneHandling=DateTimeZoneHandling.Utc;
settings.DateFormatHandling=DateFormatHandling.IsoDateFormat;
DateTime dateSerialized=JsonConvert.DeserializeObject(日期字符串,设置);
Console.WriteLine(“日期字符串:+dateString”);
Console.WriteLine(“日期序列化:+dateSerialized.ToString(“o”);
dateSerialized.Kind.Should().Be(DateTimeKind.Utc);
dateSerialized.Should().Be(dateRaw.ToUniversalTime());
dateSerialized.Should().Be(daterawastc);
}
//TODO:输出失败
//日期字符串:“2014-06-02T21:00:00.0000000”
//序列化日期:2014-06-02T21:00:00.0000000-07:00
//预期的日期和时间,但未找到。
[测试方法]
public void NEW_应_反序列化_unspecified_datestring_到_local_date()
{
string dateString=“\”2014-06-02T21:00:00.0000000\”;
DateTime dateRaw=新的DateTime(2014,6,2,21,0,0,0,DateTimeKind.未指定);
DateTime dateRawAsLocal=新的DateTime(2014,6,2,14,0,0,0,DateTimeKind.Local);
dateRawAsLocal.Should().Be(dateRaw.ToLocalTime());
JsonSerializerSettings设置=新建JsonSerializerSettings();
settings.DateTimeZoneHandling=DateTimeZoneHandling.Local;
settings.DateFormatHandling=DateFormatHandling.IsoDateFormat;
DateTime dateSerialized=JsonConvert.DeserializeObject(日期字符串,设置);
Console.WriteLine(“日期字符串:+dateString”);
Console.WriteLine(“日期序列化:+dateSerialized.ToString(“o”);
dateSerialized.Kind.Should().Be(DateTimeKind.Local);
dateSerialized.Should().Be(dateRaw.ToLocalTime());
dateSerialized.Should().Be(dateRawAsLocal);
}
[测试方法]
public void NEW_应将_unspecified_datestring_反序列化为_unspecified_date()
{
string dateString=“\”2014-06-02T21:00:00.0000000\”;//未指定,没有“Z”
DateTime dateRaw=新的DateTime(2014,6,2,21,0,0,0,DateTimeKind.未指定);
JsonSerializerSettings设置=新建JsonSerializerSettings();
settings.DateTimeZoneHandling=DateTimeZoneHandling.未指定;
settings.DateFormatHandling=DateFormatHandling.IsoDateFormat;
DateTime dateSerialized=JsonConvert.DeserializeObject(日期字符串,设置);
Console.WriteLine(“日期字符串:+dateString”);
Console.WriteLine(“日期序列化:+dateSerialized.ToString(“o”);
dateSerialized.Kind.Should().Be(DateTimeKind.Unspecified);
dateSerialized.Should().Be(dateRaw);
}

我不能100%确定您在这里寻找什么,但我认为假设JSON.Net能够满足您的所有需求而不需要一点帮助是不安全的。作为:

JSON中的日期是硬的

第一件事是确定是否支持接受未指定的日期,或者是否假设所有传入日期都是通用的,即使它们缺少尾随的Z

如果您假设所有传入日期都是通用的,那么您只需查看它们是否有尾随Z,如果没有,则添加它(不完全是生产代码,但您知道):

假设中的此更改确实要求将您测试的日期修改为Utc

如果您不想假设传入日期是通用的,而是将其视为未指定日期,则需要通过替换以下内容来更改转换传入JSON的方式:

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, settings);                
这意味着完整、修订的第一次测试将如下所示,并将通过:

    string dateString = "\"2014-06-02T21:00:00.0000000\"";
    DateTime dateRaw = new DateTime(2014, 6, 2, 21, 0, 0, 0, DateTimeKind.Unspecified);
    DateTime dateRawAsUtc = new DateTime(2014, 6, 3, 4, 0, 0, 0, DateTimeKind.Utc);
    dateRawAsUtc.Should().Be(dateRaw.ToUniversalTime());

    var oConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter();
    DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, oConverter);
    if (dateSerialized.Kind == DateTimeKind.Unspecified)
    {
        dateSerialized = dateSerialized.ToUniversalTime();
    }

    Console.WriteLine("date string: " + dateString);
    Console.WriteLine("date serialized: " + dateSerialized.ToString("o"));

    dateSerialized.Kind.Should().Be(DateTimeKind.Utc); 
    dateSerialized.Should().Be(dateRaw.ToUniversalTime());
    dateSerialized.Should().Be(dateRawAsUtc);
string dateString=“\”2014-06-02T21:00:00.0000000\”;
DateTime dateRaw=新的DateTime(2014,6,2,21,0,0,0,DateTimeKind.未指定);
DateTime dateRawAsUtc=新的日期时间(2014,6,3,4,0,0,0,DateTimeKind.Utc);
dateRawAsUtc.Should().Be(dateRaw.ToUniversalTime());
var oConverter=newnewtonsoft.Json.Converters.IsoDateTimeConverter();
DateTime dateSerialized=JsonConvert.DeserializeObject(日期字符串,oConverter);
if(dateSerialized.Kind==DateTimeKind.Unspecified)
{
dateSerialized=dateSerialized.ToUniversalTime();
}
Console.WriteLine(“日期字符串:+dateString”);
Console.WriteLine(“日期序列化:+dateSerialized.ToString(“o”);
dateSerialized.Kind.Should().Be(DateTimeKind.Utc);
dateSerialized.Should().Be(dateRaw.ToUniversalTime());
dateSerialized.Should().Be(daterawastc);

UGH!。。。但是非常感谢你的帖子/信息。。。听起来这是“精心设计的”。。。现在,关于支持unspecified的评论,这种情况经常发生——例如,开发者just myDate=new DateTime(2014,10,23);我想要一个可预测的
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, settings);                
var oConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter();
DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, oConverter);
if (dateSerialized.Kind == DateTimeKind.Unspecified)
{
    dateSerialized = dateSerialized.ToUniversalTime();
}
    string dateString = "\"2014-06-02T21:00:00.0000000\"";
    DateTime dateRaw = new DateTime(2014, 6, 2, 21, 0, 0, 0, DateTimeKind.Unspecified);
    DateTime dateRawAsUtc = new DateTime(2014, 6, 3, 4, 0, 0, 0, DateTimeKind.Utc);
    dateRawAsUtc.Should().Be(dateRaw.ToUniversalTime());

    var oConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter();
    DateTime dateSerialized = JsonConvert.DeserializeObject<DateTime>(dateString, oConverter);
    if (dateSerialized.Kind == DateTimeKind.Unspecified)
    {
        dateSerialized = dateSerialized.ToUniversalTime();
    }

    Console.WriteLine("date string: " + dateString);
    Console.WriteLine("date serialized: " + dateSerialized.ToString("o"));

    dateSerialized.Kind.Should().Be(DateTimeKind.Utc); 
    dateSerialized.Should().Be(dateRaw.ToUniversalTime());
    dateSerialized.Should().Be(dateRawAsUtc);