【问题标题】:Particular DateTime exception特定的日期时间异常
【发布时间】:2014-04-22 13:51:45
【问题描述】:

我需要将一些格式为 "MMM-yy" 的字符串转换为 DateTime。我正在处理文化“{es-ES}”

除了March(西班牙语Marzo)之外,它在所有月份都可以正常工作。 这引发了我这个异常:

'Convert.ToDateTime("Mar-13")' 抛出类型异常 'System.FormatException' System.DateTime {System.FormatException}

我试过了:

string format = "yyyyMM";
DateTime result;
CultureInfo provider = CultureInfo.InvariantCulture;
result = DateTime.ParseExact("Mar-13", format, provider);

还有这个:

DateTime date = Convert.ToDateTime("Mar-13");

这很好用,例如:

“6 月 13 日”

“2 月 13 日”

“11 月 13 日”

...

编辑 真正的问题在于:

DateTime date = Convert.ToDateTime("Ene-13"); -> 好的

DateTime date = Convert.ToDateTime("Feb-13"); -> 好的

DateTime date = Convert.ToDateTime("Mar-13"); -> 崩溃

DateTime date = Convert.ToDateTime("Abr-13"); -> 好的

....

【问题讨论】:

  • 我不明白。你在西班牙文化中有没有字符串?即使您将格式字符串固定为MMM-yyDic-13 也无法使用 InvariantCulture 转换为数据
  • 是的,我有西班牙语,我尝试使用 InvariantCulture,因为我发现它是一个可行的解决方案
  • 尝试使用CultureInfo provider = new CultureInfo("ES-es") 并将格式修复为 MMM-yy

标签: c# .net datetime


【解决方案1】:

您的日期字符串 "Mar-13" 与您的格式 "yyyyMM" 不匹配。你的格式应该是MMM-yy

你应该看到:Custom Date and Time Format Strings

按照你的格式

“MMM” - 月份的缩写名称。

"yy" - 年份,从 00 到 99。

编辑:

对于您的问题,为什么 Convert.ToDateTime("Mar-13"); 会失败。您需要查看以下代码行:

var currentCulture = new CultureInfo("es-ES");
var monthNames = currentCulture.DateTimeFormat.AbbreviatedMonthNames;
var dayOfWeeks = currentCulture.DateTimeFormat.AbbreviatedDayNames;

如果您在调试器中查看返回值,您会看到对于文化 es-ES月份名称和日期名称之间存在匹配,并且位于 mar

  • Marzo/March 作为月份
  • Martes/星期二为一天

两者都使用相同的缩写,即Mar。由于Convert.ToDateTime 会尝试对字符串使用可能的格式,因此无法将Mar 识别为月份或日期名称。这就是为什么你会得到例外。

使用DateTime.ParseExact 并指定单个或multiple possible formats 总是一个好主意。

【讨论】:

  • 但例如,如果我执行“Abr-13”,它就可以正常工作。只用“Mar”崩溃
  • @MCSI, DateTime result = DateTime.ParseExact("Mar-13", "MMM-yy", new CultureInfo("es-ES")); 这应该可以正常工作。
  • @MCSI,使用您的格式,您的字符串无法被解析。这个DateTime result = DateTime.ParseExact("Abr-13", "yyyyMM", new CultureInfo("es-ES")); 会抛出异常。
  • 好的,你是对的。真正的问题是当您不传递格式时,例如: Convert.ToDateTime("Mar-13");与其他月份完美搭配
  • @MCSI,更新了我的答案,详细解释了该行为。这主要是因为匹配了月份名称和日期名称。
【解决方案2】:

您的格式和值不匹配。试试这个:

string format = "MMM-yy";
DateTime result;
CultureInfo provider = CultureInfo.InvariantCulture;
result = DateTime.ParseExact("Mar-13", format, provider);

编辑

对于es-ES 格式提供程序,我猜MarMarzo(三月)和Martes(星期二)之间是不明确的。如果您将ParseExactproper 格式一起使用,则应该没问题:

string format = "MMM-yy";
DateTime result;
CultureInfo provider = CultureInfo.GetCultureInfo("es-ES");

// fails
result = DateTime.Parse("Mar-13", provider);

// works
result = DateTime.ParseExact("Mar-13", format, provider);
result = DateTime.ParseExact("Abr-13", format, provider);

编辑 2

这似乎是known bug。他们的解决方法是使用相似文化,但是如果您的日期格式已知,我建议使用ParseExact明确定义格式而不是让框架尝试并推断格式。

【讨论】:

  • 如果您在非西班牙语系统上使用CultureInfo.InvariantCulture,则尝试转换“abr-13”将失败。
  • 你也是对的,但正如我在上一个答案中所说......真正的问题是当你没有通过格式时,例如: Convert.ToDateTime("Mar-13") ;与其他月份完美搭配
【解决方案3】:

参考我关于自动日期时间解析背后的逻辑的回答:How Convert.ToDateTime() parses a given string when the given culture does not know the format

您可以在es-ES 文化中自动解析Abr-13,因为Abr 只能匹配为MonthToken。但是如果Mar-13 - Mar 可以匹配为MonthToken,也可以匹配为DayOfWeekToken(星期二),所以DateTime.Parse/Convert.ToDateTime 方法会混淆并抛出异常。

如果您针对es-ES 文化执行引用答案中的代码,您将在输出中看到以下内容:

   mar DayOfWeekToken 2
   Mar MonthToken 3

但完整的月份名称没有多个匹配项,因此您可以安全地解析 'marzo'、'abril' 值。

由于DateTime.Parse/Convert.ToDateTime 方法被Mar 值的这种对偶性所迷惑,我们需要使用DateTime.ParseExact 方法为其提供提示:

DateTime output = DateTime.ParseExact("Mar-13", "MMM-yy", CultureInfo.GetCultureInfo("es-ES"));

【讨论】:

    【解决方案4】:

    我认为您需要使用正确的 CultureInfo 并修复格式字符串

    CultureInfo provider = new CultureInfo("ES-es");
    DateTime result = DateTime.ParseExact("Abr-13", "MMM-yy", provider);
    

    【讨论】:

      【解决方案5】:

      您需要结合“MMM-yy”格式使用西班牙文化信息:

              string format = "MMM-yy";
              DateTime result;
              CultureInfo provider = new CultureInfo("es-ES");
              result = DateTime.ParseExact("mar-13", format, provider);
              result = DateTime.ParseExact("abr-13", format, provider);
      

      【讨论】:

        【解决方案6】:

        在我的系统上,当前的文化是 en-US,尝试转换 abril(4 月)时,以下代码将失败:

        string format = "MMM-yy";
        DateTime result;
        CultureInfo provider = CultureInfo.InvariantCulture;
        result = DateTime.ParseExact("abr-13", format, provider);
        

        因此,在我的系统上,我必须创建一种西班牙文化才能使代码正常工作:

        string format = "MMM-yy";
        DateTime result;
        CultureInfo provider = CultureInfo.CreateSpecificCulture("es-ES");
        result = DateTime.ParseExact("abr-13", format, provider);
        

        因此,您需要了解您的代码所基于的文化并采取适当的措施。

        【讨论】:

          猜你喜欢
          • 2017-09-22
          • 2020-09-18
          • 1970-01-01
          • 2015-11-02
          • 2017-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多