如何删除System.Threading.Thread.CurrentThread.CurrentCulture上的DateTime.Parse依赖项

时间:2010-07-28 12:40:18

标签: c# .net datetime

请考虑以下代码:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("fo-FO");
            var s = DateTime.MaxValue.ToString("yyyy-MM-ddTHH:mm:ssZ");
            var d = DateTime.Parse(s, CultureInfo.InvariantCulture);
            Console.WriteLine("Was able to parse with fo-FO");
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: {0}", e);
        }

        try
        {
            System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            var s = DateTime.MaxValue.ToString("yyyy-MM-ddTHH:mm:ssZ");
            var d = DateTime.Parse(s, CultureInfo.InvariantCulture);
            Console.WriteLine("Was able to parse with en-US");
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: {0}", e);
        }
    }
}

输出结果为:

Exception: System.FormatException: String was not recognized as a valid DateTime.
   at System.DateTimeParse.Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
   at System.DateTime.Parse(String s, IFormatProvider provider)
   at DateTimeTest2.Program.Main(String[] args) in C:\Projects\DateTimeTest2\DateTimeTest2\Program.cs:line 17
Was able to parse with en-US

此代码片段证明DateTime.Parse使用Thread.CurrentThread.CurrentCulture,而不管传入“InvariantCulture”的事实。我发现这非常不直观,我认为这是一个“错误”。

为什么我们必须传入CultureInfo,如果事实上它被DateTime.Parse忽略了?有没有办法以独立于CurrentCulture的方式调用DateTime.Parse?

5 个答案:

答案 0 :(得分:9)

  

此代码片段证明DateTime.Parse使用Thread.CurrentThread.CurrentCulture,无论是否传递“InvariantCulture”

我不确定这个例子是如何证明的。传递给DateTime.Parse的字符串是不同的,所以不同的结果随之而来并不奇怪。

第一个字符串的格式为23.59.59,显然InvariantCulture无法解析;第二个字符串的格式为23:59:59InvariantCulture 可以解析。有什么问题?

编辑要添加,因为显然它有所不同,我运行的是.NET 2.0,fo-FOen-US生成的字符串分别为

9999-12-31T23.59.59Z

9999-12-31T23:59:59Z

答案 1 :(得分:1)

来自MSDN的

  

不变的文化是   文化不敏感。你的申请   指定不变文化   使用空字符串(“”)或by的名称   它的语言标识符。   InvariantCulture检索实例   不变的文化。它是   与英语相关联   但没有任何国家/地区。

我找不到任何关于使用当前线程文化的参考,因为这与你说的那样是违反直觉的。

你可以(作为一种解决方法)缓存当前线程的文化,将其设置为已知的良好文化(en-US),执行解析,然后将线程的文化设置回旧值。

CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
var s = DateTime.MaxValue.ToString("yyyy-MM-ddTHH:mm:ssZ");
var d = DateTime.Parse(s, CultureInfo.InvariantCulture);
System.Threading.Thread.CurrentThread.CurrentCulture = ci;

这将保证您知道正在使用什么文化来解析DateTime字符串,并且不会影响外部调用代码,因为文化永远不会从外部角度更改。

答案 2 :(得分:1)

如果您不想在解析中考虑任何时区,可以使用

var d = DateTime.Parse(s, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);

var d = DateTime.Parse(s, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);

答案 3 :(得分:0)

两个解析都使用InvariantCulture,这实际上是对'en-US'文化的硬编码引用(可能有InvariantCulture不是'en-US'但是我没有来到他们身边)。

InvariantCulture的使用替换为new CultureInfo("en-US"),很明显为什么第一个解析不起作用。

答案 4 :(得分:0)

除了AakashM所写的内容:

我尝试在.NET 3.5 SP1中运行它。在第二种情况下,我得到一个System.FormatException,声明DateTime的值超出范围。

相关问题