6

给定以下 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.

4

2 回答 2

3

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

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

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

WhereSomeWriter创建测试输出并继承自TextWriter.

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

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

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
于 2014-06-18T22:43:56.240 回答
1

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

来自MSDN

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

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

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

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

于 2014-06-18T12:37:42.457 回答