【问题标题】:How to display DateTime with an abbreviated Time Zone?如何使用缩写的时区显示 DateTime?
【发布时间】:2010-09-15 20:58:15
【问题描述】:

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

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

如果我们的 Web 服务器运行的是 Windows Server 2k3 并且它的时区设置为 CST(或者,直到 daylight saving 切换回来,是 CDT 吗?),我希望我们的 ASP.NET Web 应用程序显示相对日期时间到那个时区,并格式化为最后显示“CST”。我意识到我可以轻松地对其进行硬编码,但出于稳健性的考虑,我真的更喜欢基于运行代码的操作系统环境设置的服务器的解决方案。

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

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

其中显示:

2008 年 10 月 7 日下午 3:40:31

我想要的只是(承诺不多!)就是让它说:

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

我可以使用 System.TimeZone.CurrentTimeZone 并使用它来正确显示“Central Daylight Time”,但是......为了简洁起见,这有点太长了。然后我是否坚持编写字符串操作例程来去除空格和任何非大写字母?虽然这可能行得通,但对我来说这似乎令人难以置信......

Googling 并在此处查看并没有产生任何适用于我的具体问题的内容。

【问题讨论】:

  • 我不敢相信在 2020 年,内置的 .NET 功能不可能做到这一点,而且我不敢相信这个问题收到了多少边缘毫无价值的回答。这是我第一次对每个答案都投了反对票。很好的问题,如果你找到真正的答案,我希望你能在这里发布!

标签: .net datetime formatting timezone tostring


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    如果您使用的是 .Net 3.0 使用 NodaTime 或其他。时区名称不符合任何约定,您可以依靠简单的字符串操作来从首字母缩略词构造缩写。 5% 的错误仍然是错误的。

    【讨论】:

    • 您是否打算在 95% 的时间里放弃盈利?
    • 虽然@micahhoover 并不是说​​你可以获得应用程序 95% 的报酬
    【解决方案3】:

    好的,已经 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]);
    }
    

    【讨论】:

      【解决方案4】:

      如果从 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 的数组可能最适合跨国公司。如果您想在紧迫的最后期限中缩短几分钟,并且您在一家美国公司,这很有效。

      【讨论】:

      • 我认为三个字符的字符串连接并没有那么糟糕,也不能证明在这里使用 StringBuilder 是合理的,尤其是因为无论如何你都在左右移动字符串。
      【解决方案5】:

      这是我刚刚为解决此问题而制定的快速破解方法。

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

      【讨论】:

      • 这种方法有一些缺陷。例如在亚利桑那州,他们使用山区标准时间并且不遵守夏令时,.NET 有一个 DaylightName 和一个 StandardName 为“美国山区标准时间”,这将在您的方法中显示“UMST”。我希望看到“MST”(在夏季和冬季)。不幸的是,.NET 框架在这里似乎不够用,所以我求助于静态查找表。
      • 这不适用于这么多时区,例如ACT 英亩时间 (UTC -5)
      • 同样,“Eastern Daylight Time”的常量实际上是“Easter Summer Time”,这将呈现为“EST”,即“Eastern Standard Time”。可惜,否则这将是一种有用的方法。也许插入一个Replace("Summer","Daylight")
      • 那么你有没有一个完美的方法来解决这个问题?
      【解决方案6】:

      有一个免费可用的库TZ4NET,其中包含这些缩写。在 .NET 3.5 之前,这也是在时区之间转换的唯一选择之一。

      如果您不想要一个单独的库,您当然可以使用 TimeZoneInfo 类生成合理缩写的映射,然后将它们提供给您的用户。

      【讨论】:

        【解决方案7】:

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

        time zone abbreviations

        【讨论】:

          【解决方案8】:

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

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

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

          这并不适用于地球上的每个时区,但适用于大多数时区。如果您需要它更健壮,那么您可能需要创建一个映射,将时区名称映射到它们的缩写。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-05-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-08
            • 2013-03-04
            • 2015-10-28
            相关资源
            最近更新 更多