C# 时区缩写
C# 时区缩写,c#,.net,timezone,C#,.net,Timezone,时区信息不提供给定时区的缩写或简称。唯一的好方法是有一个字典,它可以将缩写映射到时区.id、标准名称或DaylightName属性。但是,我搜索的所有缩写列表的来源都有不同的时区名称,即与Windows中的不同 如何在.NET中向用户显示非全名、id或任何其他名称?我不想要UtcOffset,但是时区的缩写——太平洋的PST,环球的UTC,东方标准的EST等等。是否有任何C兼容的列表或数据库,包含所有可能的时区及其缩写,与TimeZoneInfo.GetSystemTimeZones()提供给您
时区信息
不提供给定时区的缩写或简称。唯一的好方法是有一个字典,它可以将缩写映射到时区.id
、标准名称
或DaylightName
属性。但是,我搜索的所有缩写列表的来源都有不同的时区名称,即与Windows中的不同
如何在.NET中向用户显示非全名、id或任何其他名称?我不想要UtcOffset,但是时区的缩写——太平洋的PST,环球的UTC,东方标准的EST等等。是否有任何C兼容的列表或数据库,包含所有可能的时区及其缩写,与
TimeZoneInfo.GetSystemTimeZones()提供给您的那些兼容?这是一个棘手的要求,您所能做的最好的事情就是获取您选择的列表,并创建一个扩展/帮助器方法来获取给定TimeZoneInfo的缩写
一旦开始的地方是有一个版本的列表,其中包括我知道的区域
问题在于,如果给定时区存在多个缩写,则选择适当的缩写。例如,UTC可以表示为UTC或湿(西欧时间)或WEZ(西欧标准时间)或WT(西撒哈拉标准时间)
您可能希望与您的利益相关者就您将要遵循的命名约定达成一致。更新答案
我最初的答复如下,仍然有效。然而,现在有一种更简单的方法,使用。安装后,您可以执行以下操作:
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数据的嵌入式自包含副本
原始答案
正如其他人所提到的,时区缩写是模棱两可的。但如果您真的想要一个用于显示,则需要一个IANA/Olson时区数据库
您可以从Windows时区转到IANA/Olson时区,也可以转到其他方向。但是请注意,对于任何给定的Windows区域,都可能有多个IANA/Olson区域。这些映射在CLDR中维护
具有数据库和映射。您可以使用TimeZoneInfo
从.NetDateTime
或DateTimeOffset
转到NodaTimeInstant
和DateTimeZone
。从那里,你可以得到缩写名
// 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);
下面是使用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);
NodeTime.ZonedDateTime hereAndNow=NodeTime.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,
区域偏移
在我的系统中,这会产生:“2013年11月4日下午5:03:23 CDT(UTC-05:00美国/芝加哥)”
(感谢马特·约翰逊的回答,因为他提供了这个缩写存在于时区区间的线索)
如果NodaTime.zoneDateTime有一个GetZoneInterval方法,那就容易多了,但也许我遗漏了一些东西 您的问题并没有说明您的应用程序必须在哪个时区内运行,但在我的特殊情况下,我只需要关注美国时区和UTC
美国时区的缩写始终是时区名称中每个单词的第一个字符。例如,“山区标准时间”的缩写为“MST”,而“东部夏时制”的缩写为“EDT”
如果您有类似的要求,您可以很容易地直接从本地时区的名称派生出本地时区的时区缩写,如下所示(注意:这里我根据当前日期和时间确定正确的名称):
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;
}
我也有类似的问题,但不想使用第三方库(正如大多数答案所示)。如果您只想支持.Net的时区名称,并决定使用查找表,请看一看,它依靠PHP帮助生成缩写列表。您可以根据自己的需要修改其中的代码片段和表格。这对任何使用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;
}
我将所有日期存储在UTC中,通常必须在本地时间显示,因此我创建了一个扩展方法toabrevision()
或者,如果您只想从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;
}
使用方法如下:
string formattedDate = myDateTimeObject.ToLocalTimeWithTimeZoneAbbreviation()
输出:2019-06-24 02:26:31 EST
正如您所说-缩写时区名称的问题是它们有多种含义。在国际应用程序中最好避免使用。例如,至少有5种不同的时区含义。您始终可以提供缩写和偏移量。但大多数时间显示j除掉
string tz = TimeZone.CurrentTimeZone.ToAbbreviation();
string formattedDate = String.Format("{0:yyyy/MM/dd hh:mm:ss} {1}", myDate, tz);
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;
}
string formattedDate = myDateTimeObject.ToLocalTimeWithTimeZoneAbbreviation()