给出以下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.WriteLine
和string.Format
始终将字符串格式化DateTime
值相同。这种差异的解释是什么?
编辑:看起来这只发生在标准的单元测试输出(Visual Studio)中,这是我最初看到问题的地方。当代码在控制台应用程序中执行时,输出为06 17 14 ... 06 17 14
。
答案 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,你就会看到
Out
是TextWriter
,TextWriter.WriteLine
uses its assigned FormatProvider
FormatProvider
为null
to use the current thread,或assigned by constructor parameter。
我不认为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}
将始终显示/
。