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

5

我目前有一个应用程序,需要支持多种文化。传递了一个日期字符串,并将其解析为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

对于加拿大法语:

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

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

为什么格式看起来是反过来的?这是.NET 4.5的一个错误吗?

任何帮助都将不胜感激,谢谢。

注意:.NET版本为4.5


2
你有一个在加拿大文化中使用DateTime.TryParse失败的日期字符串示例吗?可以使用具有特定格式或预定义格式组的DateTime.TryParseExact。还有一件事,小写的mm表示分钟,大写的MM表示月份。 - Habib
1
你能发布导致问题的确切字符串吗?对我来说它的工作正常。 - dee-see
2
你的假设与.NET或Wikipedia不太相符。 - Hans Passant
@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)”)。 - EthanTowne
@Hans:你说得对。我把有效/无效搞混了。我会修复这个问题。谢谢。 - EthanTowne
显示剩余3条评论
3个回答

2

在加拿大文化中,数据解析肯定存在错误。如果您尝试使用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,则可以正常工作。


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则相反。 - EthanTowne
@EthanTowne 你用的是哪个版本的.NET?我这里是4.5。 - Haney
.NET 4.5也在这里。 - EthanTowne
确实非常奇怪。我会像接受的答案中提到的那样使用InvariantCulture,并使用本地文化以您喜欢的方式显示它。至少这样你的解析不会成为噩梦。 - Haney
这是否取决于您计算机上的日期格式特定设置?您是否覆盖了默认的区域设置?编辑:啊,我刚意识到布尔参数应该防止这种情况发生。 - ths
显示剩余2条评论

2
你可能需要研究一下 Invariant 文化。这是你在传递 URL 时应该使用的文化。你可以在客户端上用本地文化进行显示。
通常情况下,当你存储数据(例如在数据库或文件中)时,最好使用不变的文化。显示数据时可以使用本地文化。在传递数据时,要使用不变的文化。
更多信息请参见此处

我很快就意识到了这一点。我认为这是我最终会选择的道路。谢谢。 - EthanTowne

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接