将Windows时区转换为moment.js时区?

罗迪翁

我们在ASP.NET中有一个应用程序,该应用程序以Windows格式(通过TimeZoneInfo.Id)存储所有用户时区数据。

我们还使用moment.js和moment.js TimeZone库在客户端将UTC数据转换为用户数据。这是一个复杂的AngularJs应用程序,需要在客户端进行时区转换。

到目前为止,我们已使用NodaTime .NET库将Windows时区ID转换为Moment.js时区ID。在大多数常见时区中,效果很好。但是我们需要使此转换100%兼容。

当前似乎没有可靠的方法将Windows时区ID映射到IANA时区数据。有很多差异。

我相信现代JS应用程序经常处理时区。有时需要完全在服务器端(C#)和客户端(JS)上转换TZ。

有没有一种方法可以严格地将.NET映射/转换TimeZoneInfo为Moment.js时区对象?

乔恩·斯基特

TL; DR:

  • 在服务器端继续使用Noda Time
  • 选择使用BCL数据还是IANA数据;我个人会推荐IANA,但这是您的电话。(除其他外,IANA数据的版本更加清晰。)
  • 使用Noda Time生成moment.js数据,以便您确切知道客户端将使用什么,并且它将与您在服务器上执行的操作一致
  • 制定策略以应对数据更改时的情况

细节:

有时需要完全在服务器端(C#)和客户端(JS)上转换TZ。

你需要得到确切两侧同一时区的数据等效实施在两侧。这有问题,因为:

  • IANA时区数据会定期更新(因此您需要能够说出“使用数据2015a”)
  • Windows时区数据会定期更新
  • 我不想打赌,IANA规则的每个实现都完全相同,即使它们应该
  • 知道的是,TimeZoneInfo实施,随着时间的推移发生变化,部分是为了去除一些奇怪的错误,部分原因包括更多的数据(.NET 4.6理解时区在历史上更改其标准偏移量的概念;早期版本则不行)

使用Noda Time,您可以轻松地将BCL或IANA时区数据转换为moment.js格式-并且比Evgenyt的代码更可靠,因为TimeZoneInfo它不允许您请求转换。(由于TimeZoneInfo本身存在错误,所以口袋很小,偏移量可能会改变几个小时-不应改变,但是如果您要TimeZoneInfo完全匹配行为,则必须能够找到所有这些-Evgenyt的代码不会总是发现那些。)即使Noda Time不能TimeZoneInfo准确反映,它也应该与自身保持一致

moment.js格式看起来非常简单,因此,只要您不介意将数据传送到客户端,那绝对是一种选择。但是,您需要考虑当数据更改时该怎么做:

  • 您如何在服务器上将其取走?
  • 您如何暂时使用旧数据来应对客户?

如果确切的一致性对您来说真的很重要,则您可能希望将时区数据与时区数据版本一起发送给客户端...客户端在发布数据时可以将其呈现回服务器。(当然,我假设它正在这样做。)然后,服务器可以使用该版本,也可以拒绝客户端的请求并说有最新数据。

这是一些将Noda时区数据转换为moment.js的示例代码-在我看来还可以,但是我并没有做太多事情。它与momentjs.com中的文档匹配...注意,由于某些原因,moment.js决定对UTC后面的时区使用偏移,因此必须逆转偏移

using System;
using System.Linq;

using NodaTime;
using Newtonsoft.Json;

class Test
{
    static void Main(string[] args)
    {
        Console.WriteLine(GenerateMomentJsZoneData("Europe/London", 2010, 2020));
    }

    static string GenerateMomentJsZoneData(string tzdbId, int fromYear, int toYear)
    {
        var intervals = DateTimeZoneProviders
            .Tzdb[tzdbId]
            .GetZoneIntervals(Instant.FromUtc(fromYear, 1, 1, 0, 0),
                              Instant.FromUtc(toYear + 1, 1, 1, 0, 0))
            .ToList();

        var abbrs = intervals.Select(interval => interval.Name);
        var untils = intervals.Select(interval => interval.End.Ticks / NodaConstants.TicksPerMillisecond);
        var offsets = intervals.Select(interval => -interval.WallOffset.Ticks / NodaConstants.TicksPerMinute);
        var result = new { name = tzdbId, abbrs, untils, offsets };
        return JsonConvert.SerializeObject(result);
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章