.NET - 加拿大日期时间格式错误

Posted

技术标签:

【中文标题】.NET - 加拿大日期时间格式错误【英文标题】:.NET - Canadian DateTime Format Bug 【发布时间】:2014-08-22 17:35:06 【问题描述】:

我目前有一个需要支持多种文化的应用程序。一个日期字符串被传入并被解析为一个 DateTime 对象。为了允许多种文化,我首先设置线程的文化和 UICulture。

这是我的代码示例:

首先我设置了这个线程的文化。这是在 URL 上传递的(例如 en-us、en-ca、fr-ca):

CultureInfo ci = new CultureInfo(culture, false);
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = ci;

然后,我获取一个同样通过 URL 传入的日期字符串,并将其转换为 DateTime。根据文化,日期将以 mm/dd/yyyy 或 dd/mm/yyyy 形式传入。

我使用以下代码解析日期字符串:

DateTime DateTimeObject;
bool validDate = DateTime.TryParse(DateStringFromURL, Thread.CurrentThread.CurrentCulture, DateTimeStyles.None, out DateTimeObject);

TryParse 适用于大多数文化,并产生一个有效的日期时间对象。但是 en-ca 和 fr-ca 出现了问题。如果传入了错误的格式,则无法正确解析日期字符串。

以下显示了 .NET 对每种文化的期望格式:

         dd/MM/yyyy    MM/dd/yyyy
EN-CA      Valid        Invalid
FR-CA     Invalid        Valid

编辑: 更准确地说,这里是导致我出现问题的示例:

对于 EN-CA:

DateTime.Parse("26/08/2014") //VALID
DateTime.Parse("08/26/2014") //EXCEPTION THROWN

对于 FR-CA:

DateTime.Parse("26/08/2014") //EXCEPTION THROWN
DateTime.Parse("08/26/2014") //VALID

这与其他系统处理此文化的日期格式的方式相反。

为什么格式看起来是倒退的? 这是 .NET 4.5 的错误吗?

我们将不胜感激,谢谢。

注意:.NET 4.5 版

【问题讨论】:

您是否有一个示例日期字符串,该字符串在加拿大文化中使用 DateTime.TryParse 失败?,可以将 DateTime.TryParseExact 与特定格式或一组预定义格式一起使用。还有一件事,小写 mm 是分钟,月份是大写 MM 你能发布产生问题的确切字符串吗?它按我的预期工作。 是的,我将编辑我的问题。感谢您提供信息。 您的假设与 .NET 或 Wikipedia 都不一致。 @Hans:很可能就是这样。然而,我的假设有一些优点。从您链接到的***文章:“欧洲 dd/mm/(yy)yy(例如 31/12/(20)09)日期格式仍然广为人知,尤其是在魁北克,因为它是日期时使用的顺序法语口语(例如,trente et un décembre deux mille neuf)。MM/dd/(yy)yy(例如,Dec 31, (20)09)日期格式,用名称指定月份,也很常见,因为受到美国的影响,以及加拿大人用英语说日期的方式(例如,“January 1st, 2014)。 【参考方案1】:

您可能应该研究Invariant 文化。这就是您应该用于 URL 传递的内容。您可以在客户端上使用本地文化显示

通常,无论何时存储数据(例如,在数据库或文件中),最好使用 Invariant 文化。显示数据时,您可以使用当地文化。在传递数据时,您希望使用 Invariant 文化。

阅读更多here。

【讨论】:

我很快就会意识到这一点。我想这就是我最终要走的路。谢谢。【参考方案2】:

我相信你的假设是错误的。此控制台应用程序:

static void Main(string[] args)

    var enca = new CultureInfo("en-ca", false);
    var frca = new CultureInfo("fr-ca", false);

    Console.WriteLine("enca dd/MM/yyyy: " + ParseDate("26/08/2014", enca));
    Console.WriteLine("enca MM/dd/yyyy: " + ParseDate("08/26/2014", enca));

    Console.WriteLine("frca dd/MM/yyyy: " + ParseDate("26/08/2014", frca));
    Console.WriteLine("frca MM/dd/yyyy: " + ParseDate("08/26/2014", frca));

    Console.ReadKey();


static bool ParseDate(string date, CultureInfo culture)

    try
    
        DateTime.Parse(date, culture);
        return true;
    
    catch
    
        return false;
    

有输出:

enca dd/MM/yyyy: False
enca MM/dd/yyyy: True
frca dd/MM/yyyy: False
frca MM/dd/yyyy: True

【讨论】:

这很好奇。对于 FR-CA,这些是我得到的结果。对于 EN-CA,情况正好相反,只有“MM/dd/yyyy”是有效的。我在运行我的应用程序和在断点处停止并在即时窗口中传递不同的值时都得到了这些结果。我会尝试重现你的结果。谢谢。 我刚刚运行了那个确切的代码。我的结果和你的不一样。 FR-CA 匹配,EN-CA 则相反。 @EthanTowne 什么版本的 .NET? 4.5 在这里。 .NET 4.5 也在这里。 确实很奇怪。我会按照接受的答案中提到的那样去 InvariantCulture ,并使用当地文化随意展示它。至少这样你的解析不会是一场噩梦。【参考方案3】:

加拿大文化的数据解析肯定存在错误。如果您尝试使用 CurrentCulture = "en-CA":

DateTime.ParseExact("2014/09/20", "yyyy/MM/dd", Thread.CurrentThread.CurrentCulture)

你会得到以下异常:

A first chance exception of type 'System.FormatException' occurred in mscorlib.dll

如果您将 / 替换为其他内容(如 - 或 InvariantCulture),则效果很好。

【讨论】:

以上是关于.NET - 加拿大日期时间格式错误的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 错误的日期格式(JSON .NET)

有效日期的 Asp.net MVC DateTime 错误

将 .NET 日期/时间格式字符串转换为 Javascript 日期/时间格式字符串

Informix:.NET 驱动程序:默认日期时间格式

在 Windows C++ 中将字符串解析为日期的区域感知

将指定的时间格式转换为日期 asp.net