如何使用缩写的时区显示DateTime?

时间:2008-10-07 20:53:43

标签: .net datetime formatting timezone tostring

我知道System.TimeZone类以及DateTime.ToString()方法的许多用法。我无法找到的是一种将DateTime转换为字符串的方法,除了时间和日期信息之外,还包含三个字母的Time Zone缩写(事实上,与StackOverflow的相对工具提示大致相同)时间显示工作)。

为了让每个人都能轻松地关注和消费,让我们继续使用StackOverflow示例。如果查看相对时间显示的工具提示,它将显示完整日期,时间包括12小时格式的秒数,AM / PM指定,然后是三字母时区缩写(在他们的情况下为Coordinated)世界时间)。我意识到我可以通过使用内置方法轻松获得GMT或UTC,但我真正想要的是本地时间 - 在这种情况下,在Web服务器上。

如果我们的网络服务器正在运行Windows Server 2k3,并且它的时区设置为CST(或者,直到daylight saving切换回来,CDT就是它?),我希望我们的ASP.NET Web应用程序能够显示相对于该时区的DateTimes以及格式化为在末尾显示“CST”的日期时间。我意识到我可以轻松地对此进行硬编码,但为了保持稳健性,我真的更喜欢基于运行代码的OS环境设置的服务器的解决方案。

现在,除了时区缩写外,我使用以下代码:

myDateTime.ToString("MM/dd/yyyy hh:mm:ss tt")

显示:

10/07/2008 03:40:31 PM

所有我想要的(而且不是很多,承诺!)是这样说的:

10/07/2008 03:40:31 PM CDT

我可以使用System.TimeZone.CurrentTimeZone并使用它来正确显示“Central Daylight Time”但是......为了简洁起见,这有点太长了。我是不是写了一个字符串操作例程来去掉白色空格和任何非大写字母?虽然这可能有用,但这对我来说似乎非常糟糕......

Googling并且在这里四处看看并没有产生任何适用于我特定问题的内容。

8 个答案:

答案 0 :(得分:19)

这是我刚刚解决的快速黑客方法。

public static String TimeZoneName(DateTime dt)
{
    String sName = TimeZone.CurrentTimeZone.IsDaylightSavingTime(dt) 
        ? TimeZone.CurrentTimeZone.DaylightName 
        : TimeZone.CurrentTimeZone.StandardName;

    String sNewName = "";
    String[] sSplit = sName.Split(new char[]{' '});
    foreach (String s in sSplit)
        if (s.Length >= 1)
            sNewName += s.Substring(0, 1);

    return sNewName;
}

答案 1 :(得分:6)

有一个免费提供的库TZ4NET,它有这些缩写。在.NET 3.5之前,这也是在时区之间进行转换的唯一选择之一。

如果你不想要一个单独的库,你当然可以使用TimeZoneInfo类生成合理缩写的地图,然后只提供给你的用户。

答案 2 :(得分:3)

使用nodatime

以下函数在UTC时间内采用DateTime并使用缩写的本地系统时区对其进行格式化。在缩写时区的格式字符串中使用x。寻找自定义格式here

    public static string ConvertToFormattedLocalTimeWithTimezone(DateTime dateTimeUtc)
    {
        var tz = DateTimeZoneProviders.Tzdb.GetSystemDefault(); // Get the system's time zone
        var zdt = new ZonedDateTime(Instant.FromDateTimeUtc(dateTimeUtc), tz);
        return zdt.ToString("MM'/'dd'/'yyyy' 'hh':'mm':'ss' 'tt' 'x", CultureInfo.InvariantCulture);
    }

答案 3 :(得分:2)

我会创建一个将时区名称转换为其缩写的查找表。如果未找到匹配项,则可以返回完整的区域名称。

请参阅time zone abbreviations

答案 4 :(得分:2)

如果从DaylightName / StandardName中提取缩写,您最好使用StringBuilder构建字符串,因为字符串是不可变的。

    public static string ToCurrentTimeZoneString(this DateTime date)
    {
        string name = TimeZone.CurrentTimeZone.IsDaylightSavingTime(date) ?
            TimeZone.CurrentTimeZone.DaylightName :
            TimeZone.CurrentTimeZone.StandardName;
        return name;
    }

    public static string ToCurrentTimeZoneShortString(this DateTime date)
    {
        StringBuilder result = new StringBuilder();

        foreach (string value in date.ToCurrentTimeZoneString().Split(' '))
        {
            if (value.IsNotNullOrEmptyWithTrim())
            {
                result.Append(char.ToUpper(value[0]));
            }
        }

        return result.ToString();
    }

当然,包含KeyValuePair的数组可能最适合跨国公司。如果你想在紧迫的截止日期前刮几分钟,并且你在美国公司工作,这是有效的。

答案 5 :(得分:1)

这取决于您需要的健壮程度。

无论哪种方式,你都可能需要某种黑客攻击。一种简单的方法是用空格分割字符串,然后连接每个单词的第一个字母。即。

string[] words = tzname.Split(" ".ToCharArray());
string tzabbr = "";
foreach (string word in words)
   tzabbr += word[0];

这对地球上的每个时区都不起作用,但对大多数时区都适用。如果你需要它更强大,那么你可能需要创建一个将时区名称映射到缩写的地图。

答案 6 :(得分:0)

好的,已经4年了(差不多一周),是时候我们把LINQ带进了讨论......

将Criag和Bob的想法放在一起......

public static String TimeZoneName2(DateTime dt)
{
    var return ToCurrentTimeZoneShortString(dt)
                 .Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
    return sSplit.Aggregate("", (st,w)=> st +=w[0]);
}

除非你可以信任TimeZone永远不会返回一个包含两个连续空格的字符串:

public static String TimeZoneName3(DateTime dt)
{
    return ToCurrentTimeZoneShortString(dt).Split(' ')
                 .Aggregate("", (st,w)=> st +=w[0]);
}

答案 7 :(得分:0)

如果您使用的是< = .Net 3.0,请下载TZ4Net并使用OlsonTimeZone.CurrentTimeZone.StandardAbbreviation for> .Net 3.0使用NodaTime或其他。时区名称不符合任何惯例,您可以依赖简单的字符串操作来从首字母缩略词构造缩写。错误的5%的时间仍然是错误的。