C# 解释日期:Console.Writeline与string.Format

C# 解释日期:Console.Writeline与string.Format,c#,.net,datetime,string.format,console.writeline,C#,.net,Datetime,String.format,Console.writeline,给定以下C#代码: 。。。当短日期(在Windows 7下,Control Panel->Region and Language->additional Settings->date)设置为美国标准“M/d/yyyy”时,我得到以下结果: 06/17/14 ... 06/17/14 06/17/14 ... 06 17 14 但是,当我将短日期更改为“ddd-dd-MMM-yyyy”时,我得到以下结果: 06/17/14 ... 06/17/14 06/17/14 ... 06 17 14

给定以下C#代码:

。。。当短日期(在Windows 7下,
Control Panel->Region and Language->additional Settings->date
)设置为美国标准“
M/d/yyyy
”时,我得到以下结果:

06/17/14 ... 06/17/14
06/17/14 ... 06 17 14
但是,当我将短日期更改为“
ddd-dd-MMM-yyyy
”时,我得到以下结果:

06/17/14 ... 06/17/14
06/17/14 ... 06 17 14
我的印象是
Console.WriteLine
string.Format
的字符串格式总是
DateTime
值相同。这种差异的原因是什么


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

这是由于
格式
方法如何解释
/
符号

如果自定义格式字符串包含“/”格式说明符,则DateTime.ToString方法将显示DateSeparator的值,而不是结果字符串中的“/”

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

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


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

这种情况会出现,因为当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
,或者您的计算机设置的任何内容。所以第一项通常是错误的

但是,第二项根据其运行的位置而有所不同。作为控制台应用程序,控制台输出区域性应默认为当前线程区域性-因此它将为false。在XUnit或NUnit测试中,结果也是错误的。但在MSTest中,结果是正确的

如果你仔细研究,你会看到的

  • Out
    是一个
    文本编写器
    ,并且

  • 格式提供程序是,或者是

我不认为MSTest runner的来源是公开的,但可以得出结论,他们必须在某个地方做一些类似的事情:

Console.Out = new SomeWriter(CultureInfo.InvariantCulture);
其中
SomeWriter
创建测试输出,并从
TextWriter
继承

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

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
解决这个问题的一种方法是显式地将线程的当前区域性设置为不变区域性

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

当您显式设置格式字符串时,系统设置是什么并不重要。我认为这里还发生了一些事情。事实上,这很重要,因为“/”不是文字字符,而是分隔符,实际输出取决于文化,例如在德国,它将是一个“.”。但这并不能解释为什么在
Console.WriteLine
String.format
@Enigmativity中使用相同的显式格式时,输出会有所不同:就.NET而言,更改短日期显然等于更改区域性。我只是想知道为什么这两个方法调用的行为不一样。@Dirk:对。似乎有点奇怪。我得到的Console.WriteLine和string.Format的输出都是相同的,
06 17 14。。。06 17 14
。我使用的是Win 7,并且做了从.net framework 2.0到4.5.1的测试,我已经知道这一点。问题不在于斜杠变为空格,而是两个方法调用产生不同的结果。正如我注意到的,这似乎只发生在测试输出中。谢谢你的解释,Matt!谢谢你的提问!