How to create .NET CultureInfo with Dateformat ISO 8601?
Asked Answered
B

2

8

Is it possible to make .NET create the following output?

DateTime.UtcNow.ToString() --> "2017-11-07T00:40:00.123456Z"

Of course there is always the possibility to use ToString("s") or ToString("yyyy-MM-ddTHH:mm:ss.fffffffK"). But is there a way to adjust the default-behaviour for the parameterless ToString-Method to the desired output?

I tried changing the CurrentCulture. But the best I got was "2017-11-07 00:40:00.123456Z". I did not find a way to change the separator between the date and the time from a space to "T".

Beulabeulah answered 6/11, 2017 at 23:48 Comment(1)
I guess to make the format with a space you did something like c = new CultureInfo("en-US") { DateTimeFormat = { ShortDatePattern = "yyyy-MM-dd", LongTimePattern = "HH:mm:ss.FFFK" } }Kidskin
G
7

It is possible, but only by accessing an internal field via reflection, which is not guaranteed to work in all cases.

var culture = (CultureInfo) CultureInfo.InvariantCulture.Clone();
var field = typeof(DateTimeFormatInfo).GetField("generalLongTimePattern",
                                           BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
{
    // we found the internal field, set it
    field.SetValue(culture.DateTimeFormat, "yyyy-MM-dd'T'HH:mm:ss.FFFFFFFK");
}
else
{
    // fallback to setting the separate date and time patterns
    culture.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd";
    culture.DateTimeFormat.LongTimePattern = "HH:mm:ss.FFFFFFFK";
}
CultureInfo.CurrentCulture = culture;

Console.WriteLine(DateTime.UtcNow);  // "2017-11-07T00:53:36.6922843Z"

Note that the ISO 8601 spec does allow a space to be used instead of a T. It's just preferable to use the T.

Goldin answered 7/11, 2017 at 0:51 Comment(2)
Thank you! I won't do that anyway since I do not feel comfortable using this. Just if someone is interested: The field above is an internal "cache" for the datetime-format that is never modified. referencesource.microsoft.com/#mscorlib/system/globalization/…Beulabeulah
Yeah, I'd recommend never actually doing this. Just use ToString with a proper format specification. Hiding it like this is probably not the best idea. Maybe good in a pinch for a hacky workaround, but try to avoid it. :)Goldin
N
4

Scott Hanselmann has blogged about it here.

a little Reflectoring shows us that the default format string for System.DateTime is "G" as in System.DateTime.ToString("G") where G is one of the presets.

[...]

And gets the output he expects, indicating that "G" is the combination of a ShortDate and a LongTime.

So you should override ShortDatePattern and LongTimePattern:

I converted the code to C# and yes, it is working:

var customCulture = new CultureInfo("en-US")
{
    DateTimeFormat =
    {
        ShortDatePattern = "yyyy-MM-dd",
        LongTimePattern = "HH:mm:ss.FFFFFFFK"
    }
};

Console.WriteLine(DateTime.Now);

System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;
System.Threading.Thread.CurrentThread.CurrentUICulture = customCulture;
Console.WriteLine(DateTime.Now);

Console.ReadLine();

However, Scott has titled his post Enabling Evil for reason. Think twice before doing that!

The T is not needed, but also can not be provided. If you still need it, you need to use Reflection, as Matt answered.

Nodus answered 7/11, 2017 at 1:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.