【问题标题】:RestSharp converts Datetimes to UTCRestSharp 将日期时间转换为 UTC
【发布时间】:2017-07-20 09:17:23
【问题描述】:

我有以下问题

我正在使用 RestSharp 访问我的 API。但是当我发送 DateTime 时,它​​似乎被转换为 UTC。 我正在发送“10.06.1991 00:00”,API 得到“09.06.1991 22:00”

那么,当我的 API 获得 DateTime 对象时,我总是需要增加 2 小时?

我检查了 JSON RestSharp 发送到 API。

public class Test
{
    public int IntProperty {get;set;}
    public string StringProperty {get;set;}
    public DateTime DateTimeProperty {get;set;}
}

我的对象是

Test t = new Test{ IntProperty=3, StringProperty="string", DateTimeProperty=new DateTime(1991,06,10) }

当我通过 RestSharp 发送对象时,我的 API 接收到的 JSON 是

{
    "IntProperty":3,
    "StringProperty":"string",
    "DateTimeProperty":"09.06.1991 22:00:00"
}

知道我能做什么吗? 谢谢

【问题讨论】:

标签: c# restsharp


【解决方案1】:

接收错误数据的不是您的 API,而是您的客户端发送“错误”数据。我的 API 遇到了同样的问题。 不,这是正确的数据,但已转换为 UTC。

这里描述了确切的问题:https://github.com/restsharp/RestSharp/issues/834

因此,不要为您在 API 中获取的每个 DateTime 添加 2 小时。当另一个客户端发送未转换的日期时,您可能会更改正确的数据。

  1. 您可以检查是否在 GET 上收到正确的日期。也许 RestSharp 正在将那个“错误”的日期时间转换回 10.06.1991 00:00 - 也许你可以接受它
  2. 如果您希望数据库不包含 UTC 但您最初想要发送的数据,请不要使用默认序列化程序,请使用 JSON.Net (http://www.newtonsoft.com/json)。它不会转换为 UTC 并发送原始的 DateTime。

这是一个关于如何实现的非常好的示例:http://bytefish.de/blog/restsharp_custom_json_serializer/

  • 您编写了一个实现ISerializerIDeserializer 的自定义类
  • 在序列化中调用 JSON.Net Serialize,而在反序列化中调用 JSON.Net Deserialize

  • 您只需要像这样向您的 RestClient 添加一个处理程序:(我使用的是上述博客中描述的静态默认实例)

我的客户看起来像:

private readonly RestClient _client;

public RestApiClient(string apiAdress)
{
    _client = new RestClient(apiAdress);
    _client.AddHandler("application/json", () => NewtonsoftJsonSerializer.Default);
}

在请求中你可以设置JsonSerializer:

 IRestRequest restRequest = 
        new RestRequest(request.GetRestfulUrl(), request.Method) {
            RequestFormat = request.DataFormat, 
            JsonSerializer = NewtonsoftJsonSerializer.Default 
        };

【讨论】:

  • request 是什么变量?
  • 只是一个对象,包含请求API的路径等信息。没什么特别的。重要的是将JsonSerializer 设置为使用 Json.Net 的那个。
  • 这对我有帮助,虽然您指定的 AddHandler 现在已过时,但更改为 _client.AddHandler("application/json", () => NewtonsoftJsonSerializer.Default);
  • 对我来说问题是 json 2022-01-02 23:00 中未指定种类的日期设置为 DateTime.Kind = UTZ 而不是 Unspecified。上面的解决方案不再可用(NewtonsoftJsonSerializer.Default),但发现现在可以添加 nuget RestSharp.Serializers.NewtonsoftJson 并将处理程序设置为:client.UseNewtonsoftJson(); 现在未指定日期仍然未指定。 :)
【解决方案2】:

我猜这是因为您的DateTime 对象具有DateTime.Kind 属性等于DateTimeKind.Unspecified - 它破坏了本地和UTC 类型之间的所有转换。我的意思是某些工具假定您的 DateTime 在 Utc 中,但实际上并非如此。

所以不要与那些必须在您和您的客户之间猜测正确类型的日期时间的工具作斗争。只需在任何地方使用 UTC 并转换为本地仅显示给用户。

或者,更好的是,使用更适合处理多区时间的DateTimeOffset。适合您的情况)。

UPD。在下面的 cmets 中回答 @Matthias Burger 的问题:

您将如何处理出生日期等日期?我认为“10.06.1991”可能是生日。意味着,在 UTC 中,他的生日与 GMT 不同 - 不是吗?

一如既往 - 这取决于:)

由于时间是一件棘手的事情,你应该小心 - Jon Skeet 的博客中有一篇关于 joys of date/time arithmetic 的精彩文章。老实说,我知道这不是一个真正的答案,但是有太多不同的可能问题案例 - 我们是否需要比较日期,它们是否在同一个日历中,我们是否假设所有人都是在当地时区的午夜出生的?等等

在已经提到的NodaTime 中有一个全局和局部瞬间的概念(看看它是concepts page)。我认为对于最简单的情况,我们只需要存储和显示生日LocalDate(本地日期即时)就足够了。如果您存储本地日期并为所有人固定相同的时区,即使DateTime 也足够了(所以就像您根本不使用时区一样)。

附:顺便说一句,不知道最后一个问题是否是支票,但UTC is a standard and GMT is a time zone ;)

【讨论】:

  • 仅出于我的兴趣和更好的理解:您将如何处理出生日期等日期?我认为“10.06.1991”可能是生日。意思是,在 UTC,他的生日与 GMT 不同——不是吗?
猜你喜欢
  • 1970-01-01
  • 2021-12-31
  • 2011-01-06
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
相关资源
最近更新 更多