gpt4 book ai didi

c# - 显示 EDT 而不是 EST 的时区转换

转载 作者:太空宇宙 更新时间:2023-11-03 21:33:48 26 4
gpt4 key购买 nike

我正在使用这段代码将“东部时区”转换为“EST”。现在它显示“EDT”。您不会经常在某些地方看到那个缩写,并且想坚持使用“EST”。我如何使用 NodaTime 执行此操作?

 public static string GetTimeZoneAbbr(string timeZone)
{

var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone);

if (timeZoneInfo != null)
{
var dateTime = DateTime.UtcNow;
var instant = Instant.FromDateTimeUtc(dateTime);
var tzdbSource = TzdbDateTimeZoneSource.Default;
var tzid = tzdbSource.MapTimeZoneId(timeZoneInfo);
var dateTimeZone = DateTimeZoneProviders.Tzdb[tzid];
var zoneInterval = dateTimeZone.GetZoneInterval(instant);
return zoneInterval.Name;
}

return string.Empty;
}

最佳答案

更新

下面的答案描述了如何解析和使用 CLDR 数据。这很好,但我通过将所有这些都包含在一个库中使它变得更容易。参见 this StackOverflow answer , read my blog post ,看看the TimeZoneNames library .使用这个库比自己解析 CLDR 数据容易得多。

// You can pass either type of time zone identifier:
var tz = "America/New_York"; // IANA
var tz = "Eastern Standard Time"; // Windows

// You can get names or abbreviations for any language or locale
var names = TZNames.GetNamesForTimeZone(tz, "en-US");
var abbreviations = TZNames.GetAbbreviationsForTimeZone(tz, "en-US");

names.Generic == "Eastern Time"
names.Standard == "Eastern Standard Time"
names.Daylight == "Eastern Daylight Time"

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

原始答案

我在问题评论中写了一些关于为什么显示缩写形式是完全有效的,但请允许我也回答问题。

以另一种方式重申您的问题,您希望从 Microsoft Windows 时区 ID 开始,并以代表整个时区的人类可读字符串结束,而不仅仅是有效的时区段。

可以只给他们 TimeZoneInfo.DisplayName,但这并不总是合适的。对于美国,您可能会得到 "(UTC-05:00) Eastern Time (US & Canada) 的显示名称,并且您可以去掉前导偏移量和括号以返回 “东部时间(美国和加拿大)”。但这并不适用于所有时区,因为许多时区仅具有列出城市的显示名称,例如 "(UTC-04:00)乔治敦、拉巴斯、马瑙斯、圣胡安”

更好的方法是使用来自 Unicode CLDR Project 的数据. Noda Time 拥有此数据的部分,但不是您解决此特定问题所需的全部数据。所以我不能给你一个使用 Noda Time 的代码示例。但是,您可以对原始 CLDR 数据使用以下步骤来实现您的目标:

  1. 找到与 Windows 时区对应的 IANA 时区 ID,例如您已经在上面的代码中完成的,或者使用 CLDR Windows time zone mappings直接。

  2. CLDR MetaZones file 中查找 IANA 时区.

  3. 在 CLDR 翻译之一中查找 MetaZone data files , 或 charts such as this one .使用 "generic-long""generic-short" 模式,以及您选择的语言,例如 "en" 表示英语.

因此,在您的情况下,从 “东部标准时间” 的 Windows TimeZoneInfo.Id 开始:

  1. IANA 区域 = "America/New_York"

  2. CLDR MetaZone = "America_Eastern"

  3. generic-long [en] = “东部时间”

    generic-short [en] = "ET"

请注意,并非每个 Windows 时区都可映射到 IANA 区域,并非每个元区域都有一个短名称,并且一些从未遵循夏令时的区域将只有一个标准名称而不是通用名称。

下面是一些 C# 代码,展示了如何遍历 CLDR 的 XML 数据以获得 TimeZoneInfo 对象的通用长名称。它假定您可以访问指定路径上的 CLDR 数据。下载 the latest core.zip并提取,然后将 basePath 指向该文件夹。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;

static Dictionary<TimeZoneInfo, string> GetCldrGenericLongNames(string basePath, string language)
{
// Set some file paths
string winZonePath = basePath + @"\common\supplemental\windowsZones.xml";
string metaZonePath = basePath + @"\common\supplemental\metaZones.xml";
string langDataPath = basePath + @"\common\main\" + language + ".xml";

// Make sure the files exist
if (!File.Exists(winZonePath) || !File.Exists(metaZonePath) || !File.Exists(langDataPath))
{
throw new FileNotFoundException("Could not find CLDR files with language '" + language + "'.");
}

// Load the data files
var xmlWinZones = XDocument.Load(winZonePath);
var xmlMetaZones = XDocument.Load(metaZonePath);
var xmlLangData = XDocument.Load(langDataPath);

// Prepare the results dictionary
var results = new Dictionary<TimeZoneInfo, string>();

// Loop for each Windows time zone
foreach (var timeZoneInfo in TimeZoneInfo.GetSystemTimeZones())
{
// Get the IANA zone from the Windows zone
string pathToMapZone = "/supplementalData/windowsZones/mapTimezones/mapZone" +
"[@territory='001' and @other='" + timeZoneInfo.Id + "']";
var mapZoneNode = xmlWinZones.XPathSelectElement(pathToMapZone);
if (mapZoneNode == null) continue;
string primaryIanaZone = mapZoneNode.Attribute("type").Value;

// Get the MetaZone from the IANA zone
string pathToMetaZone = "/supplementalData/metaZones/metazoneInfo/timezone[@type='" + primaryIanaZone + "']/usesMetazone";
var metaZoneNode = xmlMetaZones.XPathSelectElements(pathToMetaZone).LastOrDefault();
if (metaZoneNode == null) continue;
string metaZone = metaZoneNode.Attribute("mzone").Value;

// Get the generic name for the MetaZone
string pathToNames = "/ldml/dates/timeZoneNames/metazone[@type='" + metaZone + "']/long";
var nameNodes = xmlLangData.XPathSelectElement(pathToNames);
var genericNameNode = nameNodes.Element("generic");
var standardNameNode = nameNodes.Element("standard");
string name = genericNameNode != null
? genericNameNode.Value
: standardNameNode != null
? standardNameNode.Value
: null;

// If we have valid results, add to the dictionary
if (name != null)
{
results.Add(timeZoneInfo, name);
}
}

return results;
}

调用它会给你一个字典,然后你可以用它来查找。示例:

// load the data once an cache it in a static variable
const string basePath = @"C:\path\to\extracted\cldr\core";
private static readonly Dictionary<TimeZoneInfo, string> timeZoneNames =
GetCldrGenericLongNames(basePath, "en");

// then later access it like this
string tzname = timeZoneNames[yourTimeZoneInfoObject];

关于c# - 显示 EDT 而不是 EST 的时区转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22890184/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com