1

.NET Web 服务
我有一个 .NET Web 服务,它返回 json 格式的 DateTime。Microsoft 指定的 DateTime 的 json 表示例如:
/Date(1302847200000+0200)/
这是根据MSDN - Stand-Alone JSON Serialization自 1970 年 1 月第一个 UTC 在 +/- 符号之前的毫秒偏移量和符号后是当地时间到 GMT 的时区偏移量。因此,对于此序列化,必须将 DateTime 值从 Web 服务的本地时间转换为 UTC。

Android (java) 客户端
在我的接收 Web 服务结果的 Android 应用程序中,我使用 Gson 解析 json。因为 .NET DateTime json 序列化不是标准(根据微软的说法,DateTime 没有这样的标准)gson 无法解析这种格式化的日期。我写了一个 Date TypeAdapter,它在客户端进行序列化和反序列化。

所以这似乎工作正常。在 UTC 中往返服务的日期时间交换。如果 .NET 的 DateTime 和 Java 的 Calendar 在将本地时间转换为 UTC 时间时会考虑完全相同的规则,那就太好了。

一个例子:瑞士自 1979 年以来就有 DST(夏令时)。Java 知道以前不存在 DST。.NET 假定它自古以来就存在。因此,当 1979 年之前的夏季日期从 .NET 转换为 UTC 并从 Java 转换回本地时间(用于演示)时,该日期在同一时区会损失一个小时。

问题 如何面对这个问题?我在描述的数据交换中是否有任何错误。我想了很多不同的解决方案。我可以想象正常工作的唯一方法是替换 .NET json DateTime 序列化/反序列化。这当然不是一个受欢迎的...

谢谢你的时间。

4

1 回答 1

3

不要使用标准的 .NET Json 序列化程序,如果您在 Java 和 .NET 之间工作,它会给您带来太多的麻烦。正如您所发现的,Microsoft 使用了一种大多数人不使用的格式。

最好的序列化程序是Newtonsoft 的 Json.NETNuGet 页面),它已成为 .NET 开发人员的事实标准。他们有一个很好的 DateTime 序列化/反序列化选项,易于使用。 有关更多信息,请查看他们在 DateTime 上的博客文章。我倾向于使用 ISO 8601,这是他们在 Json.NET v4.5 中的默认格式。

我曾经在一个企业应用程序上工作,该应用程序通过 Json 与使用多种语言创建的许多不同产品进行通信,而 Json.NET 使产品间通信变得微不足道。

处理瑞士日期时间的更新

由于您指定的是通用的中欧标准时间,.NET 不知道瑞士的日期时间规则具体是什么。要与瑞士打交道,您需要为 .NET 提供瑞士规则。查看 Wikipedia,它始于 1981 年,因此创建自定义TimeZoneInfo看起来如下所示:

// UTC Time
var date1 = new DateTime(1969, 4, 20, 2, 20,00, DateTimeKind.Utc);
Console.WriteLine("Date 1: " + date1.ToString() + " - " + date1.IsDaylightSavingTime());

// CEST
var timezone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
var date2 = TimeZoneInfo.ConvertTimeFromUtc(date1, timezone);
Console.WriteLine("Date 2: " + date2.ToString() + " - " + date2.IsDaylightSavingTime() + " " + timezone.IsAmbiguousTime(date2));

// Switzerland
var cesAdjRule = timezone.GetAdjustmentRules().Single();
var switzerlandStartTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(
        cesAdjRule.DaylightTransitionStart.TimeOfDay,
        cesAdjRule.DaylightTransitionStart.Month, cesAdjRule.DaylightTransitionStart.Week,
        cesAdjRule.DaylightTransitionStart.DayOfWeek
);
var switzerlandAdjustmentRule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(
    new DateTime(1981, 1, 1),
    DateTime.MaxValue.Date,
    cesAdjRule.DaylightDelta,
    switzerlandStartTransition,
    cesAdjRule.DaylightTransitionEnd
);
TimeZoneInfo.AdjustmentRule[] adjustments = {switzerlandAdjustmentRule};

var switzerlandTimeZone = TimeZoneInfo.CreateCustomTimeZone("Switzerland",
                                                            timezone.BaseUtcOffset,
                                                            "Switzerland",
                                                            "Switzerland",
                                                            "Switzerland",
                                                            adjustments, false);

var date3 = TimeZoneInfo.ConvertTimeFromUtc(date, timezone, switzerlandTimeZone);
Console.WriteLine("Date 3: " + date3.ToString() + " - " + date3.IsDaylightSavingTime() + " " + timezone.IsAmbiguousTime(date3));

它的输出看起来像这样(至少在我的机器上):

Date 1: 4/20/1969 2:20:00 AM - False
Date 2: 4/20/1969 4:20:00 AM - True - False
Date 3: 4/20/1969 3:20:00 AM - True - False

如您所见, IsDaylightSavingsTime 在 上为 True DateTime,但TimeZoneInfo正确转换了我们的时间。尝试其他一些组合看起来也不错。您还可以在它认为您拥有的 CEST 和瑞士之间进行转换TimeZoneInfo.CovertTime()

于 2012-04-20T14:00:20.423 回答