时区缩写

TimeZoneInfo不提供给定时区的缩写或短名称。 唯一的好办法是创build一个字典,将缩写映射到Timezone.idStandardNameDaylightName属性。 但是,我search缩写列表的所有来源都有不同的时区名称,即不同于Windows。

如何在.NET中向用户显示不是全名,ID或任何其他名称? 我不想要UtcOffset,但时区的缩写 – PST为太平洋,UTC为通用,EST – 为东部标准等。是否有任何C#兼容列表或数据库与所有可能的时区和缩写与TimeZoneInfo.GetSystemTimeZones()兼容TimeZoneInfo.GetSystemTimeZones()给你?

这是一个棘手的要求,你可以做的最好的是得到你select的列表,并创build一个扩展/帮助方法来获得给定TimeZoneInfo的缩写。

一旦开始的地方在http://www.timeanddate.com/library/abbreviations/timezones/有一个列表的版本,涵盖了我所知道的区域。;

如果给定的时区有多于一个的话,那么问题就出在select一个合适的缩写。 例如UTC可以表示为UTCWET(西欧时间)WEZ(WesteuropäischeZeit)WT(西撒哈拉标准时间)

您可能想要与您的利益相关者就您将遵循给定select的命名约定达成一致。

更新的答案

我原来的回应是低于,仍然有效。 不过,现在有一个更简单的方法,使用TimeZoneNames库 。 从Nuget安装后 ,您可以执行以下操作:

 string tzid = theTimeZoneInfo.Id; // example: "Eastern Standard time" string lang = CultureInfo.CurrentCulture.Name; // example: "en-US" var abbreviations = TZNames.GetAbbreviationsForTimeZone(tzid, lang); 

生成的对象将具有类似于以下的属性:

 abbreviations.Generic == "ET" abbreviations.Standard == "EST" abbreviations.Daylight == "EDT" 

您也可以使用这个相同的库来获取完全本地化的时区名称。 该库使用CLDR数据的embedded式自包含副本。

原来的答案

正如其他人所提到的,时区缩写是不明确的。 但是,如果您真的想要展示一个,则需要IANA / Olson时区数据库。

您可以从Windows时区到IANA / Olson时区以及其他方向。 但请注意,对于任何给定的Windows区域,可能会有多个IANA / Olson区域。 这些映射在这里保留在CLDR中。

NodaTime同时具有数据库和映射。 您可以从.Net DateTimeDateTimeOffsetTimeZoneInfo ,到NodaTime InstantDateTimeZone 。 从那里,你可以得到缩写名称。

 // starting with a .Net TimeZoneInfo var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); // You need to resolve to a specific instant in time - a noda Instant // For illustrative purposes, I'll start from a regular .Net UTC DateTime var dateTime = DateTime.UtcNow; var instant = Instant.FromDateTimeUtc(dateTime); // note that if we really wanted to just get the current instant, // it's better and easier to use the following: // var instant = SystemClock.Instance.Now; // Now let's map the Windows time zone to an IANA/Olson time zone, // using the CLDR mappings embedded in NodaTime. This will use // the *primary* mapping from the CLDR - that is, the ones marked // as "territory 001". // we need the NodaTime tzdb source. In NodaTime 1.1.0+: var tzdbSource = TzdbDateTimeZoneSource.Default; // in previous NodaTime releases: // var tzdbSource = new TzdbDateTimeZoneSource("NodaTime.TimeZones.Tzdb"); // map to the appropriate IANA/Olson tzid var tzid = tzdbSource.MapTimeZoneId(timeZoneInfo); // get a DateTimeZone from that id var dateTimeZone = DateTimeZoneProviders.Tzdb[tzid]; // Finally, let's figure out what the abbreviation is // for the instant and zone we have. // now get a ZoneInterval for the zone and the instant var zoneInterval = dateTimeZone.GetZoneInterval(instant); // finally, you can get the correct time zone abbreviation var abbreviation = zoneInterval.Name; // abbreviation will be either PST or PDT depending // on what instant was provided Debug.WriteLine(abbreviation); 

你的问题并没有说明你的应用程序必须在什么时区运行,但在我的特殊情况下,我只需要关心美国时区和UTC。

美国时区的缩写总是时区名称中每个单词的第一个字符。 例如,“Mountain Standard Time”的缩写为“MST”,“Eastern Daylight Time”的缩写为“EDT”。

如果您有类似的要求,可以直接从当地时区的名称中直接推导出当地时区的时区缩写,如下所示(注意:这里是根据当前date和时间确定正确的名称):

 string timeZoneName = TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now) ? TimeZone.CurrentTimeZone.DaylightName : TimeZone.CurrentTimeZone.StandardName; string timeZoneAbbrev = GetTzAbbreviation(timeZoneName); 

GetTzInitials()函数的代码非常简单。 值得一提的是,某些时区可能设置为墨西哥或加拿大,而这些时区的名称将在国际名称(例如“太平洋标准时间(墨西哥)”)中加以标注。 为了处理这个问题,任何括号数据都直接返回。 为上述返回的缩写将是“PST(墨西哥)”,这对我很有用。

 string GetTzAbbreviation(string timeZoneName) { string output = string.Empty; string[] timeZoneWords = timeZoneName.Split(' '); foreach (string timeZoneWord in timeZoneWords) { if (timeZoneWord[0] != '(') { output += timeZoneWord[0]; } else { output += timeZoneWord; } } return output; } 

这是另一个使用NodaTime的片段:

 NodaTime.ZonedDateTime hereAndNow = NodaTime.SystemClock.Instance.Now.InZone( NodaTime.DateTimeZoneProviders.Tzdb.GetSystemDefault()); System.TimeSpan zoneOffset = hereAndNow.ToDateTimeOffset().Offset; string sTimeDisplay = string.Format("{0:G} {1} (UTC{2}{3:hh\\:mm} {4})", hereAndNow.ToDateTimeOffset(), hereAndNow.Zone.GetZoneInterval(hereAndNow.ToInstant()).Name, zoneOffset < TimeSpan.Zero ? "-" : "+", zoneOffset, hereAndNow.Zone.Id); 

在我的系统上,这产生了:“2013年4月11日5:03:23 CDT(UTC-05:00 America / Chicago)”

(感谢马特·约翰逊(Matt Johnson)的回答,提供缩写词居住在TimeZoneInterval的线索)

如果NodaTime.ZonedDateTime有一个GetZoneInterval方法会更容易,但也许我错过了一些东西。

我有一个类似的问题,但不想使用第三方库(大多数这些答案build议)。 如果您只想支持.Net的时区名称,并决定使用查找表,请查看我的答案,这里依赖于PHP来帮助生成缩写列表。 您可以根据需要调整代码片段和表格。

这对任何使用Xamarin for iOS或Android的人都很有帮助,因为根据文档“显示名称是根据Windows操作系统安装的文化进行本地化”。 在中央时区使用此function时,对于date时间“2016-09-01 12:00:00 GMT”,此函数返回“CDT”,这正是我遇到这个问题时所需要的。

 public static string GetTimeZoneAbbreviation(DateTime time) { string timeZoneAbbr; if(time.IsDaylightSavingTime() == true) { timeZoneAbbr = TimeZoneInfo.Local.DaylightName; } else { timeZoneAbbr = TimeZoneInfo.Local.StandardName; } return timeZoneAbbr; }