Home > Software engineering >  DateTime returns wrong string on ToString(string format)
DateTime returns wrong string on ToString(string format)

Time:10-24

I found a curious occurrence today:

Background

I was trying to load some dates from db (saved as strings) and I noticed that the datetimes fetch fails because of the format on my local db, I investicate and I discover that while the class that saves and loads those values from database always use a format string like yyyy/MM/dd to save, but for whatever reason dates on my db are in the format yyyy-MM-dd.

I investigate more and I find out that the wrong values are the one I saved while testing some new features, analyzing more I find out that all of the call to DateTime.ToString(formatStr) with the aforementioned format string separate the date parts with a '-' instead of a '/' as I would expect.

The problem

At this point I whip out a simple console program with literally 4 lines, outputs in the comment.

Console.WriteLine(DateTime.Today
    .ToString("yyyy/MM/dd")); // Ouputs 2022-10-24
Console.WriteLine(DateTime.Today
    .ToString("yyyy/MM/dd", new CultureInfo("en-US"))); // Ouputs 2022-10-24
Console.WriteLine(DateTime.Today
    .ToString("yyyy/MM/dd", CultureInfo.InvariantCulture)); // Ouputs 2022/10/24
Console.WriteLine(DateTime.Today
    .ToString("yyyy/MM/dd", CultureInfo.CurrentCulture)); // Ouputs 2022-10-24

I add that for all of my colleagues the result of all of the previous lines is 2022/10/24 as I would expect, my current culture is en-US at the moment.

Conclusion

Am I missing something? Nobody I know seems to be able to replicate this but I'm getting a lot of really funny errors beacuse of this..

Edit: Corrected code snippet

CodePudding user response:

The "/" in date format string is not a literal, it has special meaning:

The "/" custom format specifier represents the date separator, which is used to differentiate years, months, and days. The appropriate localized date separator is retrieved from the DateTimeFormatInfo.DateSeparator property of the current or specified culture.

So it represents localized date separator, and the actual symbol used depends on current or specified culture.

That means in your case CultureInfo.CurrentCulture.DateTimeFormat.DateSeparator is "-" and not "/".

Now in your test console program, you do not pass culture to DateTime.ToString, you pass them to Console.WriteLine call, so they have no effect on formatting. Instead you should have done it like this:

Console.WriteLine(DateTime.Today.ToString("yyyy/MM/dd", new CultureInfo("en-US")));

Which will output what you expect.

You can also use format string which always uses "/" as separator:

DateTime.Today.ToString("yyyy'/'MM'/'dd");

Update. As for why in your case with en-US culture you see this separator. Most likely on this machine date format has been changed manually in windows settings. CultureInfo.CurrentCulture reflects this changes. As for manually created instances of CultureInfo - CultureInfo has several constructors, one of them is:

public CultureInfo(string name, bool useUserOverride)

That second parameter, useUserOverride, defines whether such changes by user will be reflected. Then, constructor you use in your example:

new CultureInfo("en-US")

Calls the constructor above with true as useUserOverride, so in this case it also reflects this changes.

If you do:

Console.WriteLine(DateTime.Today
    .ToString("yyyy/MM/dd", new CultureInfo("en-US", false)));

Then it should not use those manually changed settings and then should output what you expect.

  • Related