【问题标题】:Why doesn't DateTime.ToShortTimeString() respect the Short Time format in "Regional and Language Settings"?为什么 DateTime.ToShortTimeString() 不尊重“区域和语言设置”中的短时间格式?
【发布时间】:2010-11-20 12:07:42
【问题描述】:

我遇到了一个问题,这可能是由于我对 DateTime.ToShortTimeString() 方法的工作原理有误解。使用此函数格式化时间字符串时,我假设它会遵守 Windows 7 格式设置中的“短时间”设置

控制面板 -> 时钟、语言和区域 -> 区域和语言 -> 格式选项卡。

但是 .NET 似乎不是基于此设置而是基于当前文化选择短时间格式:

地区和语言 -> 位置 -> 当前位置

我在 Windows 7 RC 上做了一些测试:

文化:en-GB,早上 6 点:06:00,下午 6 点:18:00 // HH:mm(英国) 文化:en-GB,早上 6 点:06:00,下午 6 点:18:00 // hh:mm(英国) 文化:en-US,6AM:6:00 AM,6PM:6:00 PM // HH:mm(美国) 文化:en-US,6AM:6:00 AM,6PM:6:00 PM // hh:mm(美国) 文化:el-GR,早上 6 点:6:00 πμ,下午 6 点:6:00 μμ // HH:mm(希腊) 文化:el-GR,早上 6 点:6:00 πμ,下午 6 点:6:00 μμ // hh:mm(希腊)

我使用 el-GR,因为这是报告问题的用户的文化,他还在 Vista SP2 和 Win 7 RC 上进行了测试,结果相同。

这个问题实际上有两个方面: 1) 我对 .NET 和 Windows 格式的误解是什么? 2)基于操作系统创建短格式时间字符串(HH:mm或hh:mm tt)的最佳解决方案是什么,理想情况下这应该在Mono中工作,所以我宁愿避免从注册表或P / Invoke读取.

用于生成上述内容的方法,以供将来参考和测试。

[STAThread]
static void Main(string[] args)
{
    CultureInfo culture = CultureInfo.CurrentCulture;

    DateTime sixAm = new DateTime(2009, 07, 05, 6, 0, 0); // 6AM 
    DateTime sixPm = new DateTime(2009, 07, 05, 18, 0, 0); // 6PM

    string sixAmString = sixAm.ToShortTimeString();
    string sixPmString = sixPm.ToShortTimeString();

    string format = "Culture: {0}, 6AM: {1}, 6PM: {2}";

    string output = String.Format(format, culture, sixAmString, sixPmString);
    Console.WriteLine(output);
    Clipboard.Clear();
    Clipboard.SetText(output);

    Console.ReadKey();
}

更新: 根据下面 Mike 的 cmets,我对上述方法进行了以下更改:

以下两行

string sixAmString = sixAm.ToShortTimeString();
string sixPmString = sixPm.ToShortTimeString();

改为

string sixAmString = sixAm.ToString("t", culture);
string sixPmString = sixPm.ToString("t", culture);

我还更改了文化变量以使用 CultureInfo.CurrentUICulture。

不幸的是,这并没有像我希望的那样工作,无论 Windows 7 的“格式”选项卡中的短时间配置如何,输出都是:

文化:美国,上午 6 点:上午 6:00,下午 6 点:下午 6:00

CultureInfo.CurrentUICulture 似乎总是 en-US。

【问题讨论】:

    标签: .net datetime time formatting cultureinfo


    【解决方案1】:

    第二个问题的答案是

    DateTimeFormat.Format(DateTime.Now, "t", CultureInfo.CurrentUICulture);
    

    或

    DateTime.Now.ToString("t", CultureInfo.CurrentUICulture);
    

    实际上,使用接受 CultureInfo 的显式方法总是更好。 .Net 如何选择默认使用 CurrentCulture 或 CurrentUICulture 或 InvarinatCulture 没有一致性。

    使答案完整。我还将概述文化之间的差异。

    所以 CurrentCulture 是“控制面板 -> 时钟、语言和区域 -> 区域和语言 -> 格式选项卡”。这是您期望您的计算成为的文化。例如,您可以在美国进行会计,因此您必须在美国进行配置。

    CurrentUICulture 是“地区和语言 -> 显示语言”,表示当您从乌克兰移民时,您希望您的应用程序在 UA 本地化(但所有计算仍在美国)。

    InvariantCulture 就是所谓的与文化无关的语言环境。您应该使用它来存储信息等。实际上它是 En-US。

    注意:每个设置位于 windows 中的位置可能是错误的。但你可能有一个想法。

    【讨论】:

    • 谢谢,我将对此进行一些测试并实施。除了日期、时间、货币、小数和千位分隔符之外,文化还会影响什么?
    • 月份、工作日名称。 LTR/RTL 方向。字符串排序。带字符串的大写/小写操作。序列化。
    • CultureInfo.CurrentUICulture 似乎是 en-US,这还能在哪里配置?在检查所有内容都设置为英国后,我尝试重新设置。我还注意到,有时在运行程序后,它并没有立即获得文化变化。但是第二次运行它总是会捡起它。
    • CurrentUICulture 是您安装的 windows 的语言版本。不是选择的显示语言。在更改显示语言时尝试 Console.WriteLine( CultureInfo.CurrentUICulture ),如果您安装了英文窗口,它将停留在 en-US。更改 CurrentUICulture 包括重新安装操作系统。不建议将其用于任何日期、时间、数字、列表、货币或任何与格式相关的内容。将它用于语言本地化可能会很好。
    • @Zaz 您是否在更改显示名称后重新加载了您的个人资料(重新启动计算机或注销/登录)?我现在没有简单的方法来检查你的观察,但我很确定你错过了一些东西。我之前的一个应用程序依赖于这个属性,它按照我在帖子中解释的方式工作。
    【解决方案2】:

    我很确定在 DateTime.ToShortTimeString() 或 DateTime.ToString("t") 中未使用短时间格式字符串是一个错误,因为它已在 .NET Framework 4.0 中修复。

    【讨论】:

    • 这应该是公认的答案,因为这解释了 ShortTimePattern 不使用当前区域设置的原因。通过 3.5 项目中的单元测试和 4.0 项目中的单元测试快速验证,您将看到 3.5 忽略了区域和语言对话框中设置的任何内容
    【解决方案3】:

    回答我的每个问题:

    1) 我对 .NET 和 Windows 格式有什么误解?

    简短的回答是,“区域和语言”设置中的“短时间”设置与 .NET 的 ShortTimePattern 属性之间没有联系。但是 LongTimePattern 属性由“Long Time”设置决定。

    我修改了上述方法,将两个格式化行替换为:

    string sixAmString = sixAm.ToString("T", culture.DateTimeFormat);
    string sixPmString = sixPm.ToString("T", culture.DateTimeFormat);
    

    这是输出:

    文化:en-GB,上午 6 点:06:00:00,下午 6 点:18:00:00 // HH:mm:ss 文化:en-GB,6AM:06:00:00 AM,6PM:06:00:00 PM //hh:mm:ss tt

    this article 的底部向我解释了问题。

    2) 根据操作系统设置创建短格式时间字符串(HH:mm 或 hh:mm tt)的最佳解决方案是什么?

    我不知道最好的解决方案,但我创建了以下函数,将 LongTimeFormat 转换为 ShortTimeFormat 从而允许应用程序在用户更改“Long Time”时遵循用户选项(尽管它不会跟踪“短时间”设置)。

    static string GetShortTimeString(DateTime ShortTimeString)
    {
        DateTimeFormatInfo dateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat;
        string ShortTimePattern = dateTimeFormat.LongTimePattern.Replace(":ss", String.Empty);
        ShortTimePattern = ShortTimePattern.Replace(":s", String.Empty);
    
        return ShortTimeString.ToString(ShortTimePattern);
    }
    

    进行上述修改后的输出:

    文化:en-GB,早上 6 点:06:00,下午 6 点:18:00 文化:en-GB,6AM:06:00 AM,6PM:06:00 PM

    P/Invoke 选项是使用 GetTimeFormat 使用 DateTime.ToString(Format) 传递 TIME_NOSECONDS,如上所述。我没有对此进行测试,因为我宁愿避免使用 P/Invoke。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 2012-12-18
      • 2020-06-02
      相关资源
      最近更新 更多