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

时间:2014-06-18 05:25:12

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

给出以下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

2 个答案:

答案 0 :(得分:3)

出现这种情况是因为当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,结果是真的。

如果你浏览.NET Framework Reference Source,你就会看到

我不认为MSTest测试运行器的来源是公开的,但可以得出结论,他们必须在某处做类似的事情:

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

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

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

解决这个问题的一种方法是明确将线程的当前文化设置为不变文化。

Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

答案 1 :(得分:1)

这是由于Format方法解释/符号的方式。

来自MSDN

  

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

     

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

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

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