TypeTonConverter DateTime Output

I use 4.0, and I try to make my life easier by developing some helper methods for type conversion. The following method works fine. It converts from any string to another data type.

System.ComponentModel; public static T Convert<T>(string s) { var typeConverter = TypeDescriptor.GetConverter(typeof(T)); if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string))) { return (T)typeConverter.ConvertFrom(s); } return default(T); } //calling this method... var dateTime = MyConverter.Convert<DateTime>("13/07/2013"); // Date format "DD/mm/yyyy" // Working as expected... Taking "13" as Day, "07" as month 

Now the following method is also in the same MyConverter class, but it does not work with DateTime:

 public static bool CanConvertTo<T>(string s) { var typeConverter = TypeDescriptor.GetConverter(typeof(T)); if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string))) { return typeConverter.IsValid(s); } else return false; } 

The problem with this method is that it only accepts a date: "MM / dd / yyyy"

 // This will give exception. It is taking "13" as month, "07" as Day bool canConvert = MyConverter.CanConvertTo<DateTime>("13/07/2013"); 

EDIT As suggested by KeyboardP, I changed my method to:

 public static bool CanConvertTo<T>(string s) { TypeConverter typeConverter; if (typeof(T) == typeof(DateTime)) { typeConverter = new DateTimeConverter(); } else { typeConverter = TypeDescriptor.GetConverter(typeof(T)); } if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string))) { return typeConverter.IsValid(s); } else return false; } 

and tested. Test Results:

 var date = MyConverter.Convert<DateTime>("13/07/2013"); //return perfect date var canConvert = MyConverter.CanConvertTo<DateTime>("13/07/2013"); // returned false... 

So success with DateTimeConverter

+4
source share
2 answers

Since DateTime can have many different format styles, I would just use a DateTimeConverter than try to recreate it in a generic method.

Edit

I did a bit of ILspying, and this is what I concluded (happy that you were corrected at any time).

GetCoverter(typeof(DateTime)) will return a DateTimeConverter , so calling CanConvertFrom actually calls DateTimeConverter.CanConvertFrom . CanConvertFrom calls base.CanConvertFrom ( base as the parent class of TypeConverter).

The base.CanConvertFrom method is as follows

 public virtual bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(InstanceDescriptor); } 

Since DateTime.GetType() != typeof(InstanceDescriptor) , the return value is false . CanConvertFrom is called by the IsValid method, and since we just set the return value to false , IsValid returns false .

So, how does the Convert method work, although the same CanConvertFrom method CanConvertFrom called?

Well, the parameter you pass is of type string , not DateTime .

 typeConverter.CanConvertFrom(typeof(string)) 

In the first code snippet above, the CanConvertFrom method refers to the TypeConverter base class. If we look at DateTimeConverter.CanConvertFrom override, it looks like

 public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } 

Since we pass string as a type, this method returns true (as opposed to calling IsValid ). Since this returns true, the code continues to call

 return (T)typeConverter.ConvertFrom(s); 

(where T is a DateTime )

DateTimeConverter simply calls DateTime.Parse and ignores the culture. I'm not sure if this is a design or bug, but I would not rely on DateTime.Parse if you don't know that the string is always the same format (or you format it correctly before calling your method).

+3
source

DateTimeConverter.IsValid does not use the current culture. Here's how I got around this.

 public class FixedDateTimeConverter : DateTimeConverter { public override bool IsValid(ITypeDescriptorContext context, object value) { DateTime d; return DateTime.TryParse(value.ToString(), out d); } } 

...

 var converter = TypeDescriptor.GetConverter(typeof (T)); if (typeof (T) == typeof (DateTime)) converter = new FixedDateTimeConverter(); return converter.IsValid(null,r); 
0
source

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


All Articles