使用国家/城市而不是时区代码在时间之间转换的功能

时间:2011-11-01 05:15:09

标签: c# datetime timezone

我正在用C#编写一个程序来转换来自不同国家/地区的时间(类似this)。在通过Stack Overflow徒步旅行后,大多数人似乎对使用时区代码(例如从GMT到EDT或EST到BST)进行转换感兴趣。这让我觉得有点奇怪,因为你需要经历另一个障碍才能考虑到DST并发症。

更简单(更实际,至少对我的目的而言)是简单地指定您希望将时间转换为/的国家/城市/州。如果我们现在只关注本地时间,我已经创建了这两个函数来从本地时间转换为FileTime(基本上是UTC)并再次返回。

// Example use: convert_LocalToFile("1/11/2011 00:00:00") = 129645792000000000
long convert_LocalToFile(string time)
{
    DateTime dt = DateTime.Parse(time);
    return dt.ToFileTime();
}
// Example use: convert_FileToLocal(129645792000000000) = "1/11/2011 00:00:00"
string convert_FileToLocal(long time)
{
    return DateTime.FromFileTime(time).ToString();
}

但是,如果我们一劳永逸地解决这个问题,并且具有允许您指定国家/城市的功能,那将会很棒。规范如下:

// Example use 1: convert_AnyToFile("1/11/2011 00:00:00", "England") = 129645792000000000
// Example use 2: convert_AnyToFile("1/11/2011 00:00:00","New York") = 129645936000000000
long convert_AnyToFile(string time, string location) {
    ...
}

// Example use 1: convert_FileToAny(129645792000000000, "England") = "1/11/2011 00:00:00"
// Example use 2: convert_FileToAny(129645936000000000,"New York") = "1/11/2011 00:00:00"
string convert_FileToAny(long time, string location) {
    ...
}

所以我的问题有两个方面:有人可以填写“上述两个空函数”以使它们正常工作,并提供一种方法让C#列出所有允许作为参数的国家和城市。< / p>

------------------------编辑:而不是国家或城市,我也会用晦涩的(对我而言)TZ代码如本页所示: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones

正如已经指出的那样,我需要找到一个数据文件,从tz数据库代码映射到国家/城市/地区。在这种情况下,用“字符串代码”替换上述2个函数模板中的“字符串位置”。 'code'表示tz database time zone代码(TZ),而不是典型的time zone代码(例如EST或GMT)。

3 个答案:

答案 0 :(得分:1)

根据评论的一些指示:

对于某些转换代码,请参阅Creating a DateTime in a specific Time Zone in c# fx 3.5http://www.jarloo.com/c-convert-timezones/

对于处理时区的代码,如tz_database(又名Olson ...),请参阅http://www.twinsun.com/tz/tz-link.htmhttp://www.codeproject.com/KB/dotnet/Using_time_zones_in_NET.aspx

MSDN对相关类/方法等的引用:

<强>更新

在阅读了NodaTime(甚至不知道它存在)后,我强烈建议使用它 - 请参阅Jon Skeet的答案。

答案 1 :(得分:1)

如果您满意使用zoneinfo / Olson名称(例如“Europe / London”,“America / Los_Angeles”等),您可以查看我开始的项目Noda Time。它通常是Joda Time日历引擎的一个端口,但是新的API更加以.NET为中心。

由于缺少一些功能,它还没有进入v1,但是应该有什么效果。请注意,它解决了许多deficiencies of DateTime,特别是区分“本地日期/时间”和“分区日期/时间”(并且还应对只是时间或只是约会)。如果您想要使用Noda Time进行时区转换,那么DateTime之间会有转换 - 尽管如果可以,我建议您在代码中普遍使用它。 (如果它没有提供您想要的所有功能,请告诉我们,以便我们可以添加它们!)

请注意,在将当地时间视为特定时区时,您需要了解它可能是模棱两可的或从不存在的可能性。例如在星期天,时钟在英国回归,所以凌晨1:30发生两次。在春天,凌晨1点30分根本不会发生,因为时钟从早上1点到凌晨2点。当然,Noda Time提供了不同的处理方法,但你需要在每种情况下确定你想要做的事情:)

答案 2 :(得分:1)

正如在similar question中所指出的那样,人们需要小心,因为Windows使用了非常误导性的名称(例如:欧洲/巴黎奇怪的“浪漫标准时间”或奇怪的“东部标准时间”当官方定义另有说明时,充当ET并使用夏令时。更不用说US Eastern Standard Time)。

关于Windows'Time Zones的城市/州/国家/地区的映射,我还没有找到任何数据文件,但我会一直关注。我猜你可能需要找到从Windows时区名称转换为Olson Time Zones的数据,然后从那里找到个别城市/州/国家名称。这个链接将有助于前者: http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html

考虑到这一点,我已经填写了主要问题的空函数(感谢Jon和Yahia的指针)。第一个是主函数,是对大多数人有用的函数。另外两个是第一个函数使用的辅助函数。

我已经检查了他们,他们为夏令时工作,虽然我打赌Jon Skeet和其他人将能够找到一些讽刺,“轻微”的缺陷。例如,1601左右之前的日期将不起作用,因为Windows的文件时间不支持该日期。还建议在try / catch语句中包含对这些函数的调用,当然要捕获错误的日期输入等。

// Master conversion function
// Example use 1: convertTimezone("1/11/2011 00:00:00", "GMT Standard Time", "Eastern Standard Time") = "31/10/2011 20:00:00"
// Example use 2: convertTimezone("1/11/2011 00:00:00", "Eastern Standard Time", "GMT Standard Time") = "01/11/2011 04:00:00"
// Example use 3: convertTimezone("1/10/2011 00:00:00", "Eastern Standard Time", "GMT Standard Time") = "01/10/2011 05:00:00"
string convertTimezone(string time, string oldlocation, string newlocation)
{
    long l = convertTime_AnyToFile(time, oldlocation);
    string newtime = convertTime_FileToAny(l, newlocation);
    return newtime;
}

// Example use 1: convertTime_AnyToFile("1/11/2011 00:00:00", "GMT Standard Time") =    129645792000000000
// Example use 2: convertTime_AnyToFile("1/11/2011 00:00:00","Eastern Standard Time") = 129645936000000000
long convertTime_AnyToFile(string time, string location)
{
    DateTime a = DateTime.Parse(time  );
    DateTime b = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(a, location, "UTC");
    return b.ToFileTime();
}

// Example use 1: convertTime_FileToAny(129645792000000000, "GMT Standard Time") = "1/11/2011 00:00:00"
// Example use 2: convertTime_FileToAny(129645936000000000,"Eastern Standard Time") = "1/11/2011 00:00:00"
string convertTime_FileToAny(long time, string location)
{
    DateTime a = DateTime.FromFileTimeUtc(time);
    DateTime b = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(a, location);
    return b.ToString();
}

虽然看起来工作正常(在我做过的有限测试中),但在我自己回答之前,我可能会先等待一些反馈,因为也许有人可以改进上面的代码。