如何使用Newtonsoft.JSON JObject获取一致的日期时间值

4

我有一个使用Newtonsoft.Json库处理JSON数据的ASP.Net Core服务。

样例JSON输入中有一个字符串,其中包含一个ISO8601格式的日期值。

然而,我发现返回的等效日期有不同的时间值。

以下是示例代码 -

    var jsonString = @"{
        ""data"": {
            ""name"": ""John Doe"",
            ""dateOfBirth"": ""1990-05-25T15:54:49.119+00:00""
        }
    }";

    var jsonObj = JObject.Parse(jsonString);
    var person = jsonObj.ToObject<Person>();

    DateTime dateOfBirth = DateTime.Parse(person.Data.DateOfBirth);
    if (dateOfBirth.Kind != DateTimeKind.Utc)
    {
        dateOfBirth = dateOfBirth.ToUniversalTime();
    }
    Console.WriteLine("Date of birth is " + dateOfBirth.ToString("o"));

人类(Person)类的定义如下:-
class Person
{
    public PersonalData Data;
}

class PersonalData
{
    public  string Name { get; set; }
    public string DateOfBirth { get; set; }
}

如果我提供了""dateOfBirth"": ""1990-05-25T15:54:49.119+00:00"", 则输出为 -
Date of birth is 1990-05-25T15:54:49.0000000Z

如果我提供""dateOfBirth"": ""1990-05-25T15:54:49.119Z"",输出结果为 -
Date of birth is 1990-05-25T10:24:49.0000000Z

如您所见,输出结果不同,尽管应该是相同的。调用方可在 ISO8601 格式中设置任何日期时间字符串。
是否有一种方法可以始终处理这种情况?

如果dateOfBirth.Kind不是DateTimeKind.Utc,则应该写成 if (dateOfBirth.Kind == DateTimeKind.Local)。否则您需要将DateTimeKind.Unspecified转换为协调世界时,这意味着它将其解释为本地时间。如果它是未指定的,则应使用DateTime.SpecifyKind(dateOfBirth, DateTimeKind.Utc) - Jesse de Wit
3个回答

4
这是因为DateTime.Parse()考虑了系统时区(运行此代码的计算机的时区)。
解决方案在这里。
   var jsonString = @"{
        ""data"": {
            ""name"": ""John Doe"",
            ""dateOfBirth"": ""1990-05-25T15:54:49.119+00:00""
        }
    }";
var jsonObj = JObject.Parse(jsonString);
var person = jsonObj.ToObject<Person>();

var dateTimeOffset = DateTimeOffset.Parse(person.Data.DateOfBirth, CultureInfo.InvariantCulture);
DateTime dateOfBirth = dateTimeOffset.UtcDateTime;
Console.WriteLine("Date of birth is " + dateOfBirth.ToString("o"));

当输入为- ""dateOfBirth"": ""1990-05-25T15:54:49.119Z""时仍然存在相同的问题。 - tyrion

0

如果你使用DateTimeOffset,它应该可以解决你的问题。与其试图重新编写已经存在的信息,我会给你指出一些现有的资源:

与DateTime值相比,DateTimeOffset值的用途更加常见。因此,在应用开发中应将DateTimeOffset视为默认的日期和时间类型。

参考MSDN开发指南

了解DateTime vs DateTimeOffset的区别


我认为问题不在于 DateTime。问题出现在 Json.Net 上,当字符串带有 "Z" 后缀或 "00:00" 时,它会以不同的方式进行日期时间转换。 - tyrion
当字符串为""1990-05-25T15:54:49.119+00:00""时,它会给出正确的结果。 - tyrion

0

我已经尝试使用JsonConvert.DeserializeObject(jsonString)函数并得到了预期的输出结果。请查看这个fiddle。

https://dotnetfiddle.net/uuZvab

Person person = JsonConvert.DeserializeObject<Person>(jsonString);
                DateTime dateOfBirth = DateTime.Parse(person.Data.DateOfBirth);
                if (dateOfBirth.Kind != DateTimeKind.Utc)
                {
                    dateOfBirth = dateOfBirth.ToUniversalTime();
                }
                Console.WriteLine("Date of birth is " + dateOfBirth.ToString("o"));

在这个例子中,我不得不编写代码来执行JObject.Parse()以获取一个JObject。然而,在我的生产代码中,是asp.net框架代码将已经填充了出生日期属性的JObject交给我。 - tyrion
我应该执行 JObject.ToString() 方法来传递给 JsonConvert.DeserializeObject 方法吗? - tyrion
我认为这个可以解决问题: string json = myJObject.ToString(Newtonsoft.Json.Formatting.None); - snehgin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接