C# 时区缩写

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15302083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:22:55  来源:igfitidea点击:

Timezone Abbreviations

c#.nettimezone

提问by iLemming

TimeZoneInfodoes not provide abbreviation or a short name for a given Timezone. The only good way to do it is to have a dictionary that will map abbreviations to either Timezone.id, StandardNameor DaylightNameproperties. However, all the sources I searched for list of abbreviations have different timezone names, i.e. not the same as in Windows.

TimeZoneInfo不提供给定时区的缩写或简称。唯一的好方法是拥有一个字典,将缩写映射到Timezone.id,StandardNameDaylightName属性。但是,我在缩写列表中搜索的所有来源都有不同的时区名称,即与 Windows 中的不同。

How do you show a user not a full name, id or any other name in .NET? I don't want the UtcOffset but Timezone abbreviation - PST for Pacific, UTC - for Universal, EST - for Eastern Standard and etc. Is there any C# compatible list or database with all possible timezones and their abbreviations that compatible with those that TimeZoneInfo.GetSystemTimeZones()gives you?

你如何在 .NET 中显示用户而不是全名、ID 或任何其他名称?我不希望UTCOFFSET但时区的缩写- PST太平洋,UTC -通用,EST -东部标准等是否有任何C#兼容列表或数据库中所有可能的时区和它们的缩写,与那些兼容是TimeZoneInfo.GetSystemTimeZones()给你?

采纳答案by iLemming

This is a tricky requirement, the best you can do is get the list of your choice and create a extension / helper method to get the abbreviation for the given TimeZoneInfo.

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

Once place to start is at http://www.timeanddate.com/library/abbreviations/timezones/which has a version of list which covers the zones I am aware of.

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

The issue would be in selecting an appropriate abbreviation where more than one exists for a given timezone. For example UTCcan be represented as UTCor WET (Western European Time)or WEZ (Westeurop?ische Zeit)or WT (Western Sahara Standard Time).

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

You may want to agree with your stakeholders on the naming convention you are going to follow with the given choices.

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

回答by Matt Johnson-Pint

UPDATED ANSWER

更新的答案

My original response is below, and is still valid. However there is now an easier way, using the TimeZoneNames library. After installing from Nuget, you can do the following:

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

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

The resulting object will have the properties similar to:

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

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

You can also use this same library to get the fully localized names of the time zones. The library uses an embedded self-contained copy of the CLDR data.

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

ORIGINAL ANSWER

原答案

As others mentioned, Time zones abbreviations are ambiguous. But if you really want one for display, you need an IANA/Olson time zone database.

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

You can go from a Windows time zone to an IANA/Olson time zone and the other direction as well. But be aware that there could be multiple IANA/Olson zones for any given Windows zone. These mappings are maintained in the CLDR here.

您可以从 Windows 时区切换到 IANA/Olson 时区,也可以从另一个方向切换。但请注意,任何给定的 Windows 区域都可能有多个 IANA/Olson 区域。这些映射在此处的 CLDR 中维护。

NodaTimehas both the database and the mappings. You can go from a .Net DateTimeor DateTimeOffsetwith a TimeZoneInfo, to a NodaTime Instantand DateTimeZone. From there, you can get the abbreviation name.

NodaTime具有数据库和映射。您可以从 .NetDateTimeDateTimeOffset带有TimeZoneInfo, 到 NodaTimeInstantDateTimeZone. 从那里,您可以获得缩写名称。

// 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);

回答by BrandonLWhite

Here's another snippet using NodaTime:

这是使用 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);

On my system this yields: "4/11/2013 5:03:23 PM CDT (UTC-05:00 America/Chicago)"

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

(Thanks to Matt Johnson's answer for the clue that the abbreviation lives in TimeZoneInterval)

(感谢马特约翰逊对缩写存在于 TimeZoneInterval 的线索的回答)

It would be easier if NodaTime.ZonedDateTime had a GetZoneInterval method, but perhaps I'm missing something.

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

回答by STLDev

Your question does not indicate what time zones your application must operate within, but in my particular instance, I only have a need to be concerned with United States time zones and UTC.

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

The abbreviations of U.S. time zones are always the first characters of each word in the time zone name. For instance, the abbreviation of "Mountain Standard Time" is "MST" and the abbreviation of "Eastern Daylight Time" is "EDT".

美国时区的缩写始终是时区名称中每个单词的第一个字符。例如,“山地标准时间”的缩写是“MST”,“东部夏令时”的缩写是“EDT”。

If you have similar requirements, you can easily derive the time zone abbreviation of the local time zone from the local time zone's name directly, as follows (note: here I'm determining the proper name based on the current date and time):

如果你有类似的需求,可以直接从本地时区的名称中轻松推导出本地时区的时区缩写,如下(注意:这里我是根据当前日期和时间确定合适的名称):

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

string timeZoneAbbrev = GetTzAbbreviation(timeZoneName);

The code for the GetTzInitials()function is pretty straightforward. One thing worth mentioning is that some time zones may be set to Mexico or Canada, and the time zone names for these will come over with the country name in parenthesis, such as "Pacific Standard Time (Mexico)". To deal with this, any parenthesized data is passed back directly. The abbreviation returned for the above will be "PST(Mexico)", which works for me.

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

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;
}

回答by QuickDanger

I had a similar issue, but didn't want to use a 3rd party library (as most of these answers suggest). If you only want to support .Net's timezone names, and decide to use a lookup table, take a look at my answer over here, which leans on PHP to help generate a list of abbreviations. You can adapt the snippet there and the table to suit your needs.

我有一个类似的问题,但不想使用 3rd 方库(正如大多数这些答案所暗示的那样)。如果您只想支持 .Net 的时区名称,并决定使用查找表,请查看我的答案here,它依靠 PHP 来帮助生成缩写列表。您可以调整那里的代码段和表格以满足您的需要。

回答by Gandalf458

This is is helpful for anyone using Xamarin for iOS or Android because according to the documentation "The display name is localized based on the culture installed with the Windows operating system." When using this in the Central Time Zone, for the DateTime "2016-09-01 12:00:00 GMT", this function returns "CDT" which is exactly what I needed when I came upon this question.

这对使用 Xamarin for iOS 或 Android 的任何人都有帮助,因为根据文档“显示名称是根据 Windows 操作系统安装的区域性本地化的。” 在中央时区使用它时,对于 DateTime“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;
}

回答by Adam Hey

I store all my dates in UTC and often have to display them in local time, so I created an extension method ToAbbreviation()

我将所有日期存储在 UTC 中,并且经常必须以本地时间显示它们,因此我创建了一个扩展方法 ToAbbreviation()

    public static string ToAbbreviation(this TimeZone theTimeZone)
    {

        string timeZoneString = theTimeZone.StandardName;
        string result = string.Concat(System.Text.RegularExpressions.Regex
           .Matches(timeZoneString, "[A-Z]")
           .OfType<System.Text.RegularExpressions.Match>()
           .Select(match => match.Value));

        return result;
    }

example usage:

用法示例:

string tz = TimeZone.CurrentTimeZone.ToAbbreviation();
string formattedDate = String.Format("{0:yyyy/MM/dd hh:mm:ss} {1}", myDate, tz);

Or, if you want to just get a formatted date string from a DateTime object:

或者,如果您只想从 DateTime 对象获取格式化的日期字符串:

public static string ToLocalTimeWithTimeZoneAbbreviation(this DateTime dt)
{
    DateTime localtime = dt.ToLocalTime();
    string tz = TimeZone.CurrentTimeZone.ToAbbreviation();

    string formattedDate = String.Format("{0:yyyy/MM/dd hh:mm:ss} {1}", localtime, tz);
    return formattedDate;
}

and use as follows:

并使用如下:

string formattedDate = myDateTimeObject.ToLocalTimeWithTimeZoneAbbreviation()

output: 2019-06-24 02:26:31 EST

输出: 2019-06-24 02:26:31 EST