Reputation: 2075
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".
Upvotes: 8
Views: 4203
Reputation: 17004
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.
Upvotes: 4
Reputation: 241525
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
.
Upvotes: 7