实际上你错过了很多。
时区偏移量不是恒定的。许多时区会切换夏令时(又称“夏令时”)的偏移量。因此,当您根据每个位置(服务器、客户端、目标)的“现在”计算偏移量时,这仅反映了current offset.
在任何有 DST 的时区,当时钟向前滚动时,都会缺少一个小时,并且重复的时钟向后滚动的小时。如果您正在处理当地时间,并且预定的事件属于不明确的时间段,则您无法确定运行该事件的实际时刻。为了消除歧义,您需要told对应的偏移量是多少,或者你需要以UTC来处理。
如果您要从一个时区转换到另一个时区,则需要处理时区,而不仅仅是它们的偏移量。在.Net中,您可以使用内置的Windows时区数据库和相应的TimeZoneInfo
班级。或者,您可以使用更标准的 IANA 时区数据库,例如野田时间 http://www.nodatime.org.
当与DateTime
类型,要非常小心.Kind
属性设置为。许多函数在处理不同类型时有不同的行为。使用该方法会更安全、更有用DateTimeOffset
改为键入。
您真的不应该依赖于代码运行的服务器的时区。服务器代码应该与时区无关。你唯一应该参与的地方DateTime.Now
or TimeZoneInfo.Local
或任何类似的功能在desktop or mobile应用程序。服务器代码应该仅取决于 UTC。
我真的不明白为什么你的内部有可为空的值OutputDate
方法。没有理由这样做。此外,您实际上正在获取差异的绝对值 - 这会降低方向性。时区偏移确实是定向的,因此您当前的实现可能会得到无效的结果。
-
我查看了 Quartz.net API,他们似乎更喜欢您在 UTC 中安排活动时间。这是一件非常好的事情,因为 UTC 不存在歧义问题。来自Quartz.Net 教程 http://quartznet.sourceforge.net/tutorial/lesson_1.html, the trigger.StartTimeUtc
显然是UTCDateTime
。既然你说你不能使用最新版本,我还检查了他们较旧的1.0 API文档,它仍然是UTC。
Update: 石英网2.5 https://www.quartz-scheduler.net/2017/02/18/quartznet-2.5-released.html更大可以更好地处理时区。看#317 https://github.com/quartznet/quartznet/pull/317了解详情。
让我们将所有这些放在一起作为您的示例用例。纽约市的一位客户希望在当地时区的下午 2:00 运行作业。服务器的时区无关紧要,他创建作业的时间也无关紧要。
// June 6, 2013 2:00 PM Kind = Unspecified
DateTime dt = new DateTime(2013, 6, 13, 14, 0, 0);
// This is the correct Windows time zone for New York
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
// Get the time in UTC - The kind matters here.
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt, tz);
// Feed it to a quartz event trigger
trigger.StartTimeUtc = utc;
当我在第三步中将时间转换为 UTC 时,如果时间不明确,.Net 会假设您想要standard时间而不是daylight时间。如果您想更具体,则必须检查是否有歧义,然后询问用户他们想要两个当地时间中的哪一个。那么你就必须使用DateTimeOffset
以区分它们。如果您认为您可能需要这个,请告诉我,我可以制作一个样本,但它有点复杂。
为了更好地衡量,如果您想使用 IANA 时区野田时间 http://www.nodatime.org,它看起来像这样:
LocalDateTime ldt = new LocalDateTime(2013, 6, 13, 14, 0);
DateTimeZone tz = DateTimeZoneProviders.Tzdb["America/New_York"];
ZonedDateTime zdt = ldt.InZoneLeniently(tz);
trigger.StartTimeUtc = zdt.ToDateTimeUtc();
The InZoneLeniently
方法将给出与上面代码相同的行为。但如果需要,您还可以指定其他选项。
哦,这并不重要,但印度是+5:30
, not +5