类型转换器日期时间格式问题

本文关键字:格式 问题 时间 日期 类型转换 转换器 类型 | 更新日期: 2023-09-27 18:20:55

我正在使用4.0,我试图通过开发一些用于类型转换的辅助方法来简化我的生活。以下方法工作正常。它将从任何字符串转换为其他数据类型。

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

现在,以下方法也属于同一类MyConverter,但它不能很好地与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;
}

这种方法的问题是,它只接受日期格式:"MM/dd/yyyy">

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

编辑按照KeyboardP的建议,我将方法更改为:

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;
}

并经过测试。测试结果是:

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

所以没有成功DateTimeConverter

类型转换器日期时间格式问题

由于DateTime可以有许多不同的格式样式,我只使用 DateTimeConverter,而不是尝试在通用方法中重新创建它。

编辑

做了一些ILsping,这就是我的结论(很高兴在任何一点上得到纠正(。

GetCoverter(typeof(DateTime))将返回一个DateTimeConverter所以调用CanConvertFrom实际上是在调用DateTimeConverter.CanConvertFromCanConvertFrom调用base.CanConvertFrom(base是父类型转换器类(。

基地。CanConvertFrom 方法看起来像这样

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

DateTime.GetType() != typeof(InstanceDescriptor) 以来,返回值为 falseCanConvertFromIsValid 方法调用,由于我们刚刚确定返回值为 falseIsValid返回false

那么,即使调用了相同的CanConvertFrom方法,Convert方法为什么会起作用呢?

好吧,您传递的参数是类型 string ,而不是 DateTime .

typeConverter.CanConvertFrom(typeof(string))

在上面的第一个代码片段中,CanConvertFrom 方法适用于TypeConverter基类。如果我们看一下DateTimeConverter.CanConvertFrom覆盖,它看起来像这样

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

由于我们将String作为类型传递,因此此方法返回 true(与IsValid调用不同(。因为这返回 true,所以代码继续调用

return (T)typeConverter.ConvertFrom(s);

(其中 T 是DateTime (

DateTimeConverter只是称DateTime.Parse,忽视文化。我不确定这是设计使然还是错误,但我不会依赖DateTime.Parse,除非您知道字符串始终具有相同的格式(或者在调用方法之前正确格式化(。

DateTimeConverter.IsValid 不使用当前区域性。这是我解决这个问题的方法

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);