开发者

DateTimeFormatInfo.InvariantInfo vs CultureInfo.InvariantCulture

I am trying to parse DateTime, with an exact format being accepted from client input.

Which one is better

bool success = DateTime.TryParseExact(value, "dd-MMM-yyyy",
   DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out dateTime);

OR

bool success = DateTime.TryParseExact(value, "dd-MMM-yyyy", 
 开发者_开发问答   CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime);

Of course, this code is inside a common static method that is called wherever parsing of date is required.


If you look at the signature for DateTime.TryParseExact, it takes an IFormatProvider as the third argument. Both DateTimeFormatInfo.InvariantInfo and CultureInfo.InvariantCulture implement this interface, so you are actually calling the same method on DateTime in both cases.

Internally, if you use CultureInfo.InvariantCulture, its DateTimeFormat property is called to get a DateTimeFormatInfo instance. If you use DateTimeFormatInfo.InvariantInfo, this is used directly. The DateTimeFormatInfo call will be slightly quicker as it has to perform less instructions, but this will be so marginal as to make no difference in (almost) all cases.

The main difference between the two approaches is the syntax. Use whichever one you find clearest.


They will give the same results.
And it is very unlikely there would be any difference in performance.

So use whatever you think is most readable. My choice would be DateTimeFormatInfo.InvariantInfo for being slightly more to the point.


For anyone who like me ended up here from google, I found the following post by Matt Weber was quite useful to understand the implementation details:

http://badecho.com/2011/07/datetimeformatinfo-currentinfo-vs-cultureinfo-currentculture-datetimeformat-vs/

Let me quote most of the article here in case the link breaks at some point:

DateTimeFormatInfo.CurrentInfo

This will directly return another DateTimeFormatInfo instance that is set to the current culture. It does the following in order to do this:

  1. Gets the CultureInfo from the current thread’s CurrentCulture property (Thread.CurrentThread.CurrentCulture). Note that when you are accessing the current thread’s CurrentCulture property, you are basically accessing the CultureInfo.CurrentCulture property (which simply returns Thread.CurrentThread.CurrentCulture).
  2. Returns a direct reference to the date time format if the thread’s current culture instance is the base CultureInfo type itself, and not a derivation. The DateTimeFormat property of the CultureInfo object does not come into play here; instead, what we’re directly reading from the CultureInfo object’s dateTimeInfo private field.
  3. If the thread’s current culture instance has null assigned to its date time information field, then the CultureInfo‘s GetFormat method is invoked, which returns a DateTimeFormatInfo instance which is then returned.
  4. If the current thread’s culture instance is actually an object type that derives from CultureInfo, then it will always make a call to CultureInfo.GetFormat, and never read from the CultureInfo.dateTimeInfo field directly.

So, if you’re ever dealing with objects deriving from CultureInfo and setting the thread’s current culture to use them, be aware that you can modify the way the DateTimeFormatInfo is returned by overriding the CultureInfo’s GetFormat method.

DateTimeFormatInfo.InvariantInfo

This will return another DateTimeFormatInfo instance set to the culturally-insensitive culture. It does the following to do this:

  1. If the current Application Domain already has created a culturally-insensitive DateTimeFormatInfo instance, this is returned.
  2. Otherwise, a new instance is created using the public default constructor of DateTimeFormatInfo.
  3. The Calendar exposed by new DateTimeFormatInfo instance is set to read only.
  4. The new DateTimeFormatInfo instance itself is set to readonly, and then returned.

So, unlike DateTimeFormatInfo.CurrentInfo, the InvariantInfo property is initialized once per application domain, not per thread. Not a very big surprise, but may be important to know just in the event you’re doing anything adventurous and (most likely) irresponsible.

CultureInfo.CurrentCulture.DateTimeFormat

This will return a DateTimeFormatInfo object set to use the current culture. This is achieved by the following:

  1. Because we’re accessing CultureInfo.CurrentCulture, the current thread’s CurrentCulture is used as the culture (Thread.CurrentThread.CurrentCulture).
  2. If the current thread’s culture instance already has a DateTimeFormatInfo instance initialized, that’ll be returned (i.e. if the dateTimeInfo is not null, then that is returned).
  3. Otherwise, a new DateTimeFormatInfo object is created by directly initializing a new DateTimeFormatInfo instance and passing the culture data to the constructor.
  4. The DateTimeFormatInfo instance is set to readonly.
  5. A call is made to Thread.MemoryBarrier, and then the newly initialized DateTimeFormatInfo instance is assigned to the dateTimeInfo field.

How Does CultureInfo.CurrentCulture.DateTimeFormat Relate to DateTimeFormat.CurrentInfo?

  1. The CultureInfo.CurrentCulture.DateTimeFormat property is what is responsible for actually initializing the DateTimeFormatInfo instance that gets returned; calling DateTimeFormat.CurrentInfo results in a call made to the culture’s GetFormat method, which itself will return its own CultureInfo.DateTimeFormat property. So, regardless of where you start, you seem to end up in the same place. Technically, calling CultureInfo.CurrentCulture.DateTimeFormat is more direct than calling DateTimeFormat.CurrentInfo, which will end up calling just that.
  2. Differences begin to arise when one starts talking about object types derived from CultureInfo. Let’s say we wish for our custom CultureInfo class to return a DateTimeFormatInfo instance which is modified in some fashion that differs from the norm. By override CultureInfo.GetFormat, which is a virtual method, we can achieve this for calls made to DateTimeFormat.CurrentInfo, which will call this method.
  3. However, because CultureInfo.DateTimeFormat is a static property, and because the instantiation of the DateTimeFormatInfo object is done directly inside this property, there is no way to override this behavior. Therefore, we can easily end up in a situation where DateTimeFormatInfo.CurrentInfo returns a differently composed DateTimeFormatInfo instance than what we get with CultureInfo.CurrentCulture.DateTimeFormat (assuming the current culture is our custom culture class).
  4. This makes our desire of ours one that may be impossible to fulfill (customizing the creation-related logic behind a custom culture’s date time format). Hopefully no one out there needs to do this.

CultureInfo.InvariantCulture.DateTimeFormat

  1. This will return a culturally-insensitive DateTimeFormatInfo.
  2. The invariant culture is created one per application domain, inside (indirectly) the static constructor of the CultureInfo class.
  3. Once the invariant CultureInfo instance is created, the rest of the process of creating the DateTimeFormatInfo mirrors that of the previous section.

How Does CultureInfo.InvariantCulture.DateTimeFormat Relate to DateTimeFormat.InvariantInfo?

  1. These two properties, unlike their CurrentCulture-ish brethren, are completely unrelated in how they initialize the DateTimeFormatInfo instance that they return.
  2. The DateTimeFormat.InvariantInfo property does not actually deal with culture at all. It simply initializes a new DateTimeFormatInfo instance using that class’s default constructor.
  3. Although their creation mechanisms are unlinked, they are similar in that one cannot exert any influence in the creation of these constructs from derived classes, as far as I am aware.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜