时区缩写

iLe*_*ing 48 .net c# timezone

TimeZoneInfo不为给定时区提供缩写或短名称.这样做的唯一的好办法是有一个字典,地图缩写来要么Timezone.id,StandardNameDaylightName性质.但是,我搜索缩写列表的所有源都有不同的时区名称,即与Windows中的不同.

如何在.NET中向用户显示不是全名,id或任何其他名称?我不想要UtcOffset而是Timezone缩写 - 太平洋的PST,UTC - 适用于Universal,EST - 适用于东部标准等.是否有任何C#兼容列表或数据库包含所有可能的时区及其缩写,与TimeZoneInfo.GetSystemTimeZones()您提供的那些兼容?

Mat*_*int 65

更新的答案

我的原始回复如下,仍然有效.但是,使用TimeZoneNames库现在有一种更简单的方法.从Nuget安装,您可以执行以下操作:

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

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

abbreviations.Generic == "ET"
abbreviations.Standard == "EST"
abbreviations.Daylight == "EDT"
Run Code Online (Sandbox Code Playgroud)

您还可以使用此相同的库来获取时区的完全本地化名称.该库使用CLDR数据的嵌入式自包含副本.

原始答案

正如其他人所提到的,时区缩写是模棱两可的.但如果你真的想要一个用于显示,你需要一个IANA/Olson时区数据库.

您可以从Windows时区转到IANA/Olson时区,也可以转到其他方向.但请注意,任何给定的Windows区域都可能有多个IANA/Olson区域.这些映射在此处保留在CLDR中.

NodaTime同时具有数据库和映射.您可以从.Net DateTimeDateTimeOffset使用TimeZoneInfo,到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);
Run Code Online (Sandbox Code Playgroud)


小智 13

这是一个棘手的要求,您可以做的最好的事情是获取您选择的列表并创建扩展/帮助方法以获取给定TimeZoneInfo的缩写.

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

问题在于选择适当的缩写,其中给定时区存在多个缩写.例如,UTC可以表示为UTCWET(西欧时间)WEZ(WesteuropäischeZeit)WT(西撒哈拉标准时间).

您可能希望与您的利益相关者就您将遵循给定选择的命名约定达成一致.


STL*_*Dev 12

您的问题并未指出您的应用程序必须在哪个时区内运行,但在我的特定情况下,我只需要关注美国时区和UTC.

美国时区的缩写始终是时区名称中每个单词的第一个字符.例如,"Mountain Standard Time"的缩写是"MST","Eastern Daylight Time"的缩写是"EDT".

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

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

string timeZoneAbbrev = GetTzAbbreviation(timeZoneName);
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么不使用非常简单的正则表达式来获取缩写?`Regex.Replace(timeZoneName, "[^AZ]", "")` (2认同)

Bra*_*ite 5

这是使用 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);
Run Code Online (Sandbox Code Playgroud)

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

(感谢 Matt Johnson 的回答,提供了该缩写存在于 TimeZoneInterval 中的线索)

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