比较LocalDateTime不同时区的Nodatime [英] Comparing LocalDateTime for Different Time Zones in Nodatime

查看:404
本文介绍了比较LocalDateTime不同时区的Nodatime的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个应用程序,允许用户安排一个事件。用户提供使用时区选择器的Olson时区,以及日期和时间表示,通过ASP日历选择器和第三方AJAX时间选择器事件(故的DateTime 供应将始终以相同的模式)。我比较用户希望的时间和时区的用户提供我们的服务器的时间和时区,并触发事件的用户期望它被解雇的时刻。

据我所知,有阅读此链接在nodatime谷歌组,(使用 WithZone )将一个 ZonedDateTime 至另一时区是相当简单的(一旦我有从 LocalDateTime 用户的事件映射到一个 ZonedDateTime ,很明显)。我并不需要担心偏移和之间,也就是说,凤凰和芝加哥会得到妥善占夏令时间差。

我原本转换服务器的时间(<$ C C $> DateTime.Now )到 ZonedDateTime 相比这种方式,但看完后,<一个href="http://stackoverflow.com/questions/16575438/determine-how-to-calculate-times-across-different-timezones-using-nodatime-and-w">this在SO链接我转向使用 IClock

到目前为止,测试一切正常,但我很担心其他的情况,我可能不会检测为。根据对NodaTime文档:

  

最大的疑难杂症的转换 LocalDateTime ZonedDateTime - 它有一些你需要考虑极端情况。

我已经通过文件读取彻底我认为这个疑难杂症是在参考了当年的那些时间,要么不发生或出现两次。这些时间将永远不会被设置为活动时间为我们的用户,但我确实使用了 LenientResolver 他们。是否有任何其他陷阱 - 当我从 LocalDateTime 转换为 ZonedDateTime ,我失去了什么或将夏令时结束纠缠着我?

此外,我需要用户的 ZonedDateTime 到服务器时时间段之前比较转换(我现在所做的),或者是这样的不必要的(甚至是错误的)一步?将NodaTime能够恰当地比较(不夏令问题)如果我是比较活动的,而不是未转化 ZonedDateTime (事件的 ZonedDateTime 转换到服务器时区后),以当前的服务器 ZonedDateTime (见下面code,第三至最后一行)?当通过code踩着我可以看到的时间和偏移,但我很担心,这样做可能是引入的问题过于简单化了。

 受保护的功能EventIsReady(BYVAL insTimeZone作为字符串,BYVAL EVENTDATE为DATETIME)作为布尔
        昏暗的时钟作为IClock = SystemClock.Instance
        现在灰暗即时= clock.Now

        服务器时区(美国/芝加哥),不幸的是没有UTC
        昏暗区= DateTimeZoneProviders.Tzdb(美国/芝加哥)
        昏暗的serverZonedDateTime = now.InZone(区)

        用户时区
        昏暗userTimeZone作为NodaTime.DateTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull(insTimeZone)
        昏暗userEventLocalDateTime = LocalDateTime.FromDateTime(EVENTDATE)
        昏暗eventZonedDateTime = userTimeZone.ResolveLocal(userEventLocalDateTime,Resolvers.LenientResolver)
        昏暗eventTimeInServerTimeZone = eventZonedDateTime.WithZone(区)

        昏暗isReady由于布尔= FALSE
        如果eventTimeInServerTimeZone&GT; = serverZonedDateTime然后
            isReady = TRUE
        结束如果
        返回isReady
    端功能
 

解决方案

这听起来像你在正确的轨道上。

关于 LenientResolver ,一定要意识到自己的行为。它使用 ReturnStartOfIntervalAfter 的春天正向差距, ReturnLater 秋季回重叠。

IMHO,这不是对于未来事件的调度的最佳配置。 (见问题#295 ),和试试这个:

VB.NET

公共共享只读SchedulingResolver作为ZoneLocalMappingResolver = _   Resolvers.CreateMappingResolver(Resolvers.ReturnEarlier,_   AddressOf ReturnForwardShifted) 公共共享功能ReturnForwardShifted(local作为LocalDateTime,_   区作为DateTimeZone,作为ZoneInterval之前,作为ZoneInterval后)_   作为ZonedDateTime     昏暗newLocal作为LocalDateTime = local.PlusTicks(after.Savings.Ticks)     返回新ZonedDateTime(newLocal,区,after.WallOffset) 端功能

C#

公共静态只读ZoneLocalMappingResolver SchedulingResolver =   Resolvers.CreateMappingResolver(Resolvers.ReturnEarlier,ReturnForwardShifted); 公共静态ZonedDateTime ReturnForwardShifted(LocalDateTime地方,   DateTimeZone区,ZoneInterval之前,ZoneInterval后) {     LocalDateTime newLocal = local.PlusTicks(after.Savings.Ticks);     返回新ZonedDateTime(newLocal,区,after.WallOffset); }

对于服务器的时区 - 你应该离开那个从你的code。您的code的不应该关心的是服务器的时区。相反,叫 ToInstant() ZonedDateTime (你的 eventZonedDateTime 变量),然后比较,与即时从返回 clock.Now

I am working on an application that allows a user to schedule an event. The user supplies an Olson time zone by using a Time Zone Picker, and a date and time for said event through an asp calendar picker and third-party ajax time picker (so the DateTime supplied will always be in the same pattern). I compare the time the user wants and the time zone the user supplies with our server's time and its time zone, and fire the event the instant the user expects it to be fired.

From what I understand, having read this link at the nodatime google group, converting one ZonedDateTime to another time zone (using WithZone) is fairly straightforward (once I have the user's event mapped from LocalDateTime to a ZonedDateTime, obviously). I don't need to worry about offsets, and daylight savings time differences between, say, Pheonix and Chicago will be properly accounted for.

I had originally converted the server's time (DateTime.Now) to a ZonedDateTime and compared this way, but after reading this link on SO I switched to using IClock.

So far in testing everything is working out, but I am worried about corner cases that I might not be testing for. According to the documentation for NodaTime:

The biggest "gotcha" is converting LocalDateTime to ZonedDateTime - it has some corner cases you need to consider.

I have read through the documentation thoroughly and I assume that this gotcha is in reference to those times of the year that either do not occur or that occur twice. These times will never be set as event times for our users but I do use the LenientResolver for them. Are there any other gotchas - when I convert from LocalDateTime to ZonedDateTime, am I missing anything or will daylight savings time end up haunting me?

Also, do I need to convert the user's ZonedDateTime to the server time zone before comparison (which I am doing now) or is this an unnecessary (or even erroneous) step? Will NodaTime be able to compare properly (without daylight savings problems) if I were to compare the event's unconverted ZonedDateTime (instead of the event's ZonedDateTime after conversion to the server time zone) to the current server ZonedDateTime (see code below, third to last line)? When stepping through the code I can see the times and offsets, but I'm worried that doing this might be an oversimplification that introduces problems.

Protected Function EventIsReady(ByVal insTimeZone As String, ByVal eventDate As DateTime) As Boolean
        Dim clock As IClock = SystemClock.Instance
        Dim now As Instant = clock.Now

        'server time zone (America/Chicago), unfortunately not UTC
        Dim zone = DateTimeZoneProviders.Tzdb("America/Chicago")
        Dim serverZonedDateTime = now.InZone(zone)

        'user time zone
        Dim userTimeZone As NodaTime.DateTimeZone = NodaTime.DateTimeZoneProviders.Tzdb.GetZoneOrNull(insTimeZone)
        Dim userEventLocalDateTime = LocalDateTime.FromDateTime(eventDate)
        Dim eventZonedDateTime = userTimeZone.ResolveLocal(userEventLocalDateTime, Resolvers.LenientResolver)
        Dim eventTimeInServerTimeZone = eventZonedDateTime.WithZone(zone)

        Dim isReady As Boolean = False
        If eventTimeInServerTimeZone >= serverZonedDateTime Then
            isReady = True
        End If
        Return isReady
    End Function

解决方案

It sounds like you're on the right track.

Regarding LenientResolver, make sure you are aware of its behavior. It uses ReturnStartOfIntervalAfter for the spring-forward gap, and ReturnLater for the fall-back overlap.

IMHO, that isn't the best configuration for scheduling of future events. (See Issue #295), and try this instead:

VB.NET

Public Shared ReadOnly SchedulingResolver As ZoneLocalMappingResolver = _
  Resolvers.CreateMappingResolver(Resolvers.ReturnEarlier, _
  AddressOf ReturnForwardShifted)

Public Shared Function ReturnForwardShifted(local As LocalDateTime, _
  zone As DateTimeZone, before As ZoneInterval, after As ZoneInterval) _
  As ZonedDateTime
    Dim newLocal As LocalDateTime = local.PlusTicks(after.Savings.Ticks)
    Return New ZonedDateTime(newLocal, zone, after.WallOffset)
End Function

C#

public static readonly ZoneLocalMappingResolver SchedulingResolver =
  Resolvers.CreateMappingResolver(Resolvers.ReturnEarlier, ReturnForwardShifted);

public static ZonedDateTime ReturnForwardShifted(LocalDateTime local,
  DateTimeZone zone, ZoneInterval before, ZoneInterval after)
{
    LocalDateTime newLocal = local.PlusTicks(after.Savings.Ticks);
    return new ZonedDateTime(newLocal, zone, after.WallOffset);
}

Regarding the server's time zone - you should leave that out of your code. Your code should not care what the time zone of the server is. Instead, call ToInstant() on the ZonedDateTime (your eventZonedDateTime variable), then compare that with the Instant returned from clock.Now.

这篇关于比较LocalDateTime不同时区的Nodatime的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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