10

我遇到了一个问题,这可能是由于我对 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 在下面的评论,我对上述方法进行了以下更改:

以下两行

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 总是在美国。

4

3 回答 3

5

你的第二个问题的答案是

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 中的位置。但你可能有一个想法。

于 2009-08-18T07:12:00.060 回答
2

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

于 2013-04-03T17:45:36.563 回答
1

回答我的每个问题:

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

这篇文章的底部向我解释了这个问题。

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

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

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。

于 2009-08-18T17:44:24.690 回答