如何处理在.NET / java中以不同的方式实现"Local Time to UTC Conversion"



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

安卓(java)客户端
在我的接收 Web 服务结果的 Android 应用程序中,我使用 Gson 解析 json。由于 .NET DateTime json 序列化不是标准(根据 Microsoft 日期时间没有此类标准),因此 gson 无法分析此类格式化日期。我编写了一个日期类型适配器,它在客户端进行序列化和反序列化。

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

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

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

谢谢你的时间。

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

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

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

关于处理瑞士日期时间的最新情况

由于你指定的是通用的中欧标准时间,因此 .NET 不知道瑞士的日期时间规则具体是什么。 要处理瑞士问题,您需要为 .NET 提供瑞士规则。 查看维基百科,它始于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

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

最新更新