Interpreting Dates: Console.Writeline vs. string.Format

Given the following C # code:

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

... when a short date (under Windows 7, Control Panel -> Region and Language -> Additonal Settings -> Date ) is set to the US standard " M/d/yyyy ", I get the following:

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

However, when I change the short date to " ddd dd MMM yyyy ", I get the following:

 06/17/14 ... 06 17 14 

I got the impression that Console.WriteLine and string.Format always build formatted DateTime values ​​the same way. What is the explanation for this discrepancy?

EDIT: It appears that this only happens on the standard unit test output (Visual Studio), where I initially saw the problem. When the code is executed in the console application, the output is 06 17 14 ... 06 17 14 .

+6
source share
2 answers

This situation occurs because when MSTest redirects the console output to the test window, it passes CultureInfo.InvariantCulture to the TextWriter associated with the console.

You can check this with the following:

 var threadCulture = Thread.CurrentThread.CurrentCulture; var consoleCulture = Console.Out.FormatProvider; Console.WriteLine(threadCulture.Equals(CultureInfo.InvariantCulture)); Console.WriteLine(consoleCulture.Equals(CultureInfo.InvariantCulture)); 

If you do not change it, the current thread culture is usually en-US or regardless of your computer. Therefore, the first element will usually be false.

But the second element changes depending on where it works from. As a console application, the console output culture should default to the current thread culture, so it will be false. In XUnit or NUnit tests, the result is also incorrect. But in MSTest the result is correct.

If you dig up . The reference source of the .NET Framework , you will see that

I do not think that the sources for the MSTest tester are publicly available, but we can conclude that they should do something like this somewhere:

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

Where SomeWriter generates test output and inherits from TextWriter .

String.Format , String.Format other hand, String.Format always use the current thread culture, unless you specifically provide another culture.

One way around this would be to explicitly link the current flow culture to the invariant culture.

 Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; 
+3
source

This is due to the way the Format method interprets the / character.

From MSDN

If the custom format string contains the format specifier "/", the DateTime.ToString method displays the DateSeparator instead of the "/" in the result string.

The DateSeparator property determines the string that replaces the date separator ("/" custom date and time format specifier) ​​in the result string in the formatting operation. It also defines the date separator string in the parsing operation.

When you change the format, the default character changes to a space character.

If you need to display the / character, it can be escaped with \ . Thus, changing the format string to {0:MM\/dd\/yy} will always display / .

+1
source

Source: https://habr.com/ru/post/970983/


All Articles