在时区之间进行转换 [英] Converting between time zones with Noda Time

查看:170
本文介绍了在时区之间进行转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在努力确保我们的遗留后端可以根据用户当前的时区(或更具体的偏移量)来支持解决日期时间。我们的服务器在东部标准时间,大多数的日期时间都来自那里。但是,对于其他时区的用户,在检索这些日期时间时,需要转换到其时区(或在这种情况下为偏移量)。此外,来自用户的日期时间将必须在服务器上的持久性之前转换为东部标准时间。鉴于我们正在开发的前端是基于Web的,我可以在几分钟内检索用户的偏移量,并将该值传递到标题内的服务层。我看了Noda时代,认为这是一个很棒的API。它强制我在更精细的事情中考虑时间,但我仍然不能100%确定我已经正确使用它。以下是我为上述转换所写的方法。我已经测试过,他们似乎工作。鉴于上述情况,这看起来像是正确使用图书馆吗?我正在考虑日期时间吗?

I'm currently trying to ensure that our legacy back-end can support resolving date times based on the user's current time zone (or, more specifically offset). Our servers are in eastern standard time, and most of our date times originate there. However, for users that are in other time zones, a conversion to their time zone (or, in this case, offset) is needed when retrieving those date times. Also, date times coming from the user will have to be converted to eastern standard time before persistence on the server. Given that the front end we are developing is web-based, I am able to retrieve the user's offset in minutes and pass that value into my service layer within the header. I looked at Noda Time and think it's a great API. It did force me to think about time in a more refined matter, but I am still not 100% sure that I've properly used it correctly. Here are the methods that I wrote for the conversions described above. I've tested them and they seem to work. Given the scenario above, does this look like a proper use of the library? Am I thinking about date times properly?

public static DateTime ConvertToUtcFromEasternTimeZone(DateTime easternDateTime)
{
    NodaTime.DateTimeZone easternTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/New_York");
    ZoneLocalMappingResolver customResolver = Resolvers.CreateMappingResolver(Resolvers.ReturnLater, Resolvers.ReturnStartOfIntervalAfter);
    var easternLocalDateTime = LocalDateTime.FromDateTime(easternDateTime);
    var easternZonedDateTime = easternTimeZone.ResolveLocal(easternLocalDateTime, customResolver);
    return easternZonedDateTime.ToDateTimeUtc();
}

public static DateTime ConvertToEasternTimeZoneFromUtc(DateTime utcDateTime)
{
    NodaTime.DateTimeZone easternTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull("America/New_York");
    NodaTime.DateTimeZone utcTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull("UTC");
    ZoneLocalMappingResolver customResolver = Resolvers.CreateMappingResolver(Resolvers.ReturnLater, Resolvers.ReturnStartOfIntervalAfter);
    var utcLocal = LocalDateTime.FromDateTime(utcDateTime);
    var utcZonedDateTime = utcTimeZone.ResolveLocal(utcLocal, customResolver);
    var easternZonedDateTime = utcZonedDateTime.ToInstant().InZone(easternTimeZone);
    return easternZonedDateTime.ToDateTimeUnspecified();
}

public static DateTime ConvertToUtc(DateTime dateTime, int offsetInMinutes)
{
    LocalDateTime localDateTime = LocalDateTime.FromDateTime(dateTime);
    var convertedDateTime = localDateTime.PlusMinutes(offsetInMinutes).ToDateTimeUnspecified();
    return convertedDateTime;
}

public static DateTime ConvertFromUtc(DateTime dateTime, int offsetInMinutes)
{
    LocalDateTime localDateTime = LocalDateTime.FromDateTime(dateTime);
    var convertedDateTime = localDateTime.PlusMinutes(-offsetInMinutes).ToDateTimeUnspecified();
    return convertedDateTime;
}

这里的想法是,时区在UTC时间之间解决和数据库中的时区。当我在客户端时间和UTC时间之间进行解析时,偏移量就很重要。

The idea here is that time zone matters when I'm resolving between UTC time and the time zone in the database. When I'm resolving between the client time and UTC time then offset matters.

将来,我们可以持续UTC时间,这将更容易。目前,这个解决方案是一个暂停的差距。

In the future, we can persist UTC time, and this will be easier. Currently, this solution is a stop gap.

这个想法是我们要从...开始

The idea is that we are going to go from...

客户端 - > UTC +/-偏移量 - > UTC - >东部时间 - >数据库

client -> UTC +/- offset -> UTC -> Eastern Time -> database

数据库 - >东部时间 - > UTC - > UTC +/- offset - >客户端

database -> Eastern Time -> UTC -> UTC +/- offset -> client

最终...

客户端 - > UTC +/- offset - > UTC - >数据库

client -> UTC +/- offset -> UTC -> database

数据库 - > UTC - > UTC +/- offset - >客户端

database -> UTC -> UTC +/- offset -> client

推荐答案

您的第一种方法看起来不错,虽然我们不知道 customResolver 是什么。

Your first method looks okay, although we don't know what customResolver is.

你的第二个方法是有点偏离。我建议:

Your second method is a bit off. I'd suggest:

public static DateTime ConvertToEasternTimeZoneFromUtc(DateTime utcDateTime)
{
    var easternTimeZone = DateTimeZoneProviders.Tzdb["America/New_York"];
    return Instant.FromDateTimeUtc(utcDateTime)
                  .InZone(easternTimeZone)
                  .ToDateTimeUnspecified();
}

请注意,您不需要每次查找东部时区方法调用 - 只需要:

Note that you don't need to look up the Eastern time zone in every method call - just have:

private static readonly DateTimeZone EasternTimeZone = 
    DateTimeZoneProviders.Tzdb["America/New_York"];

...然后在任何地方使用。

... then use that everywhere.

你的第三种和第四种方法不是我认为惯用的 - 对于你应该使用的第三种方法:

Your third and fourth methods aren't what I'd think of as idiomatic - for the third method you should use:

public static DateTime ConvertToUtc(DateTime dateTime, int offsetInMinutes)
{
    var offset = Offset.FromMinutes(offsetInMinutes);
    var localDateTime = LocalDateTime.FromDateTime(dateTime);
    return new OffsetDateTime(localDateTime, offset).ToInstant()
                                                    .ToDateTimeUtc();
}

第四种方法似乎有点棘手,因为我们不提供一切应该使用 OffsetDateTime 进行转换。你使用的代码可能还可以,但如果你可以使用 OffsetDateTime ,那肯定会更干净。

The fourth method seems a bit trickier, as we don't provide everything we should in terms of conversions with OffsetDateTime. The code you've used is probably okay, but it would certainly be cleaner if you could use OffsetDateTime.

编辑:我现在已经添加了一个方法到 Instant ,使第四种方法更清洁。它将是1.2.0的一部分,您可以使用:

I've now added a method to Instant to make the fourth method cleaner. It will be part of 1.2.0, and you can use:

public static DateTime ConvertFromUtc(DateTime dateTime, int offsetInMinutes)
{
    var offset = Offset.FromMinutes(offsetInMinutes);
    var instant = Instant.FromDateTimeUtc(dateTime);
    return instant.WithOffset(offset)
                  .LocalDateTime
                  .ToDateTimeUnspecified();
}

这篇关于在时区之间进行转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆