【问题标题】:Interpreting dates: Console.Writeline vs. string.Format解释日期:Console.Writeline 与 string.Format
【发布时间】:2014-06-18 05:25:11
【问题描述】:

给定以下 C# 代码:

var dt = DateTime.Now;
Console.WriteLine("{0:MM/dd/yy} ... {1}", dt, string.Format("{0:MM/dd/yy}", dt));

...当短日期(在 Windows 7 下,Control Panel -> Region and Language -> Additonal Settings -> Date)设置为美国标准“M/d/yyyy”时,我明白了:

06/17/14 ... 06/17/14

但是,当我将短日期更改为“ddd dd MMM yyyy”时,我得到了:

06/17/14 ... 06 17 14

我的印象是 Console.WriteLinestring.Format 的字符串格式总是相同的 DateTime 值。这种差异的解释是什么?

编辑: 看起来这只发生在标准单元测试输出 (Visual Studio) 中,这是我最初看到问题的地方。当代码在控制台应用程序中执行时,输出为06 17 14 ... 06 17 14

【问题讨论】:

  • 当您明确设置格式字符串时,您的系统设置是什么并不重要。我认为这里发生了其他事情。
  • 实际上它可能很重要,因为“/”不是文字字符而是分隔符,实际输出取决于文化,例如在德国,这将是一个“。”。但这并不能解释为什么在 Console.WriteLineString.Format 中使用相同的显式格式时输出会不同。
  • @Enigmativity:嗯,就 .NET 而言,改变短日期显然等于改变文化。我只是想知道为什么这两个方法调用的行为不一样。
  • @Dirk:对。看起来很奇怪。
  • 我得到相同的输出 Console.WriteLine 和 string.Format 是 06 17 14 ... 06 17 14 。我正在使用 Win 7 并从 .net framework 2.0 到 4.5.1 进行了测试

标签: c# .net datetime string.format console.writeline


【解决方案1】:

出现这种情况是因为当 MSTest 将控制台输出重定向到测试窗口时,它会将CultureInfo.InvariantCulture 传递给与控制台关联的TextWriter

您可以通过以下方式验证这一点:

var threadCulture = Thread.CurrentThread.CurrentCulture;
var consoleCulture = Console.Out.FormatProvider;

Console.WriteLine(threadCulture.Equals(CultureInfo.InvariantCulture));
Console.WriteLine(consoleCulture.Equals(CultureInfo.InvariantCulture));

除非您更改它,否则线程的当前文化通常类似于en-US,或者您的计算机设置的任何内容。所以第一项通常是假的。

但第二个项目因运行位置而异。作为一个控制台应用程序,控制台输出文化应该默认为当前线程文化——所以它会是假的。在 XUnit 或 NUnit 测试中,结果也是错误的。但在 MSTest 中,结果为真。

如果你仔细研究.NET Framework Reference Source,你会看到

我不认为 MSTest 测试运行程序的来源是公开的,但可以得出结论,他们必须在某处执行以下操作:

Console.Out = new SomeWriter(CultureInfo.InvariantCulture);

SomeWriter 创建测试输出并从TextWriter 继承。

另一方面,String.Format 将始终使用线程的当前文化,除非您特别提供不同的文化。

解决此问题的一种方法是将线程的当前文化显式设置为不变文化。

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

【讨论】:

  • 感谢您的解释,马特!
  • 感谢您提出的好问题!
【解决方案2】:

这是由于Format 方法如何解释/ 符号。

来自MSDN

如果自定义格式字符串包含“/”格式说明符,DateTime.ToString 方法将显示 DateSeparator 的值以代替结果字符串中的“/”。

DateSeparator 属性定义在格式化操作的结果字符串中替换日期分隔符(“/”自定义日期和时间格式说明符)的字符串。它还在解析操作中定义日期分隔符字符串。

当您更改格式时,默认符号更改为空格字符。

如果需要显示/字符,可以使用\进行转义。因此将格式字符串更改为{0:MM\/dd\/yy} 将始终显示/

【讨论】:

  • 我已经知道了。问题不在于斜杠更改为空格,问题在于两个方法调用产生不同的结果。正如我所指出的,这似乎只发生在测试输出中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-21
  • 2015-12-27
  • 2013-10-17
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多