确定Olson TZID和本地DateTime的时间偏移



我需要确定时间偏移,给定事件的Olson TZID和事件的DateTime

我想我可以在Noda Time的帮助下完成这项任务,但我是新来的,需要帮助——一个实际API调用序列的例子来执行这项任务。

关于我们正在使用和做什么的更多细节。

  1. 我们正在运行基于ASP.NET+SQL Server的网站。我们网站的用户输入并保存在不同地点发生的事件。对于每个事件,Lat/Long和带有(该事件的)时间偏移的DateTime都是必填字段
  2. 数据输入有多种情况,有时Lat/Long是先输入的,有时DateTime是。系统允许根据地址或地图点确定Lat/Long。我们希望时间偏移在大多数情况下与Lat/Long保持一致,因为我们通常希望DateTime作为该事件的本地输入
  3. 我们使用SQL Server DateTimeOffset字段来存储数据
  4. 我们不想依赖第三方网络服务来确定补偿,但更希望我们的系统能够做到这一点

我可以自由下载和使用任何必要的工具或数据。我已经从下载了形状文件http://efele.net/maps/tz/并使用Shape2SQLhttp://goo.gl/u7AUy以将它们转换为具有TZID和GEOM的SQL Server表。
我知道如何通过查询该表从Lat/Long获取TZID。
我需要的是根据TZID和DateTime确定时间偏移。

感谢Jon Skeet和Matt Johnson在Noda Time Google Group上提供的答案http://goo.gl/I9unm0.Jon解释了如何在给定Olson TZID和NodaTime LocalDateTime值的情况下获得Microsoft BCL DateTimeOffset值。Matt指出了一个在给定ZonedDateTime的情况下确定DST是否处于活动状态的例子:NodaTime中的System.TimeZoneInfo.IsDaylightSavingTime等效值是什么?

我将写一篇博客文章,总结我从Lat/Long获得Olson TZID、将DateTime字符串解析为LocalDateTime并确定DateTimeOffset的经验。我将在那里展示GetTmzIdByLocation(纬度、经度)和GetRoughDateTimeOffsetByLocation(经度、纬度)方法是如何工作的,以及为什么我需要这两种方法(第一种方法不适用于海洋上的位置)。一旦我写了这篇文章,我会在这里添加一条评论。

请注意,在下面的代码中解析DateTime字符串还不是最佳的;正如Matt在Google Group的一篇帖子(上面的链接)中解释的那样,使用Noda Time工具比BCL更好。请参阅上的相关问题http://goo.gl/ZRZ7XP

我当前的代码:

public object GetDateTimeOffset(string latitude, string longitude, string dateTime)
{
var tzFound = false;
var isDST = false;
var tmpDateTime = new DateTimeOffset(DateTime.Now).DateTime;
if (!String.IsNullOrEmpty(dateTime))
{
try
{
// Note: Looks stupid? I need to throw away TimeZone Offset specified in dateTime string (if any).
// Funny thing is that calling DateTime.Parse(dateTime) would automatically modify DateTime for its value in a system timezone.
tmpDateTime = DateTimeOffset.Parse(dateTime).DateTime;
}
catch (Exception) { }
}
try
{
var tmzID = GetTmzIdByLocation(latitude, longitude);
DateTimeOffset result;
if (String.IsNullOrEmpty(tmzID) || tmzID.ToLower() == "uninhabited")   // TimeZone is unknown, it's probably an ocean, so we would just return time offest based on Lat/Long. 
{
var offset = GetRoughDateTimeOffsetByLocation(latitude, longitude);
result = new DateTimeOffset(tmpDateTime, TimeSpan.FromMinutes(offset * 60));  // This only works correctly if tmpDateTime.Kind = Unspecified, see http://goo.gl/at3Vba
}                                                                      // A known TimeZone is found, we can adjust for DST using Noda Time calls below.
else
{
tzFound = true;
// This was provided by Jon Skeet
var localDateTime = LocalDateTime.FromDateTime(tmpDateTime); // See Noda Time docs at http://goo.gl/XseiSa
var dateTimeZone = DateTimeZoneProviders.Tzdb[tmzID];
var zonedDateTime = localDateTime.InZoneLeniently(dateTimeZone);  // See Noda Time docs at http://goo.gl/AqE8Qo
result = zonedDateTime.ToDateTimeOffset(); // BCL DateTimeOffset
isDST = zonedDateTime.IsDaylightSavingsTime();
}
return new { result = result.ToString(IncidentDateFormat), tzFound, isDST };
}
catch (Exception ex)
{
IMAPLog.LogEvent(System.Reflection.MethodBase.GetCurrentMethod().Name, "", ex);
throw new CustomHttpException("Unable to get timezone offset.");
}
}

用于确定DST是否处于活动状态的扩展方法(由Matt Johnson提供)NodaTime中的System.TimeZoneInfo.IsDaylightSavingTime等效值是多少?

public static class NodaTimeUtil
{
// An extension method by Matt Johnson - on Stack Overflow at http://goo.gl/ymy7Wb
public static bool IsDaylightSavingsTime(this ZonedDateTime zonedDateTime)
{
var instant = zonedDateTime.ToInstant();
var zoneInterval = zonedDateTime.Zone.GetZoneInterval(instant);
return zoneInterval.Savings != Offset.Zero;
}
}

相关内容

  • 没有找到相关文章

最新更新