为什么DateTime.ParseExact()不能使用"M/d/yyyy"解析"9/1/2009"?

63

我有一个字符串长这样:“9/1/2009”。我想将其转换为DateTime对象(使用C#)。

这个方法可以实现:

DateTime.Parse("9/1/2009", new CultureInfo("en-US"));

但我不明白为什么这个不起作用:

DateTime.ParseExact("9/1/2009", "M/d/yyyy", null);

日期中没有单词(如“September”),我知道具体的格式,因此我宁愿使用ParseExact方法(我不明白为什么需要CultureInfo)。但是我一直收到可怕的“String was not recognized as a valid DateTime”异常。

谢谢

稍作跟进。以下是三种可行的方法:

DateTime.ParseExact("9/1/2009", "M'/'d'/'yyyy", null);
DateTime.ParseExact("9/1/2009", "M/d/yyyy", CultureInfo.InvariantCulture);
DateTime.Parse("9/1/2009", new CultureInfo("en-US"));

以下是三个不起作用的示例:

DateTime.ParseExact("9/1/2009", "M/d/yyyy", CultureInfo.CurrentCulture);
DateTime.ParseExact("9/1/2009", "M/d/yyyy", new CultureInfo("en-US"));
DateTime.ParseExact("9/1/2009", "M/d/yyyy", null);

所以,Parse() 使用 "en-US" 是可以的,但是 ParseExact 不行...这是否出乎意料?


你使用的是哪个版本的.NET?当我在Win7上执行上面第二行PowerShell v2时,它可以正常工作。 - Lee
我正在xp上使用 .net 3.5。默认文化是en-us。 - Jimmy
1
在字符串“M/d/yyyy”中,每个斜杠“/”都被替换为“culture.DateTimeFormat.DateSeparator”字符串。当您提供null作为格式化程序时,将使用当前文化。现在这取决于当前文化是否具有“/”或其他一些字符串(如“-”或“.”)作为其DateSeparator。 - Jeppe Stig Nielsen
7个回答

98
我怀疑问题在于格式字符串中的斜杠与数据中的斜杠不同。这是格式字符串中的特定于文化的日期分隔符字符,而最后一个参数为null表示“使用当前区域设置”。如果您要么转义斜杠(“M'/'d'/'yyyy”)要么指定CultureInfo.InvariantCulture,那么就可以了。
如果有人想要重现这个问题:
// Works
DateTime dt = DateTime.ParseExact("9/1/2009", "M'/'d'/'yyyy", 
                                  new CultureInfo("de-DE"));

// Works
DateTime dt = DateTime.ParseExact("9/1/2009", "M/d/yyyy", 
                                  new CultureInfo("en-US"));

// Works
DateTime dt = DateTime.ParseExact("9/1/2009", "M/d/yyyy", 
                                  CultureInfo.InvariantCulture);

// Fails
DateTime dt = DateTime.ParseExact("9/1/2009", "M/d/yyyy", 
                                  new CultureInfo("de-DE"));

我不确定为什么你的第二个例子对你起作用了。那对我来说不管用。对于这个日期字符串,使用CultureInfo("en-US")可以与Parse()一起工作,但不能与此日期字符串和格式字符串一起使用ParseExact。 - Jimmy
1
@Jimmy:这取决于你的意图。在这种情况下,/被用作一个确切的斜杠而不是一个与文化相关的分隔符(即使使用的文化是"InvariantCulture")。因此,更好地表达你的意图的选项是带引号的斜杠(你选择的那个)。 - Sam Harwell
@Jon,DateTime.ParseExact 的一个参数是 CultureInfo。所以如果我写:new CultureInfo("de-DE"),这意味着我知道日期是用 . 分隔的。那么为什么我仍然需要按照格式写成 M/d/yyyy 而不是 M.d.yyyy 呢?我们不是说我知道日期是用 . 分隔的吗?我很难理解这一点。如果我通过文化认识到了某些东西,我就知道它应该是什么样子。但是如果你告诉我用户输入了 9@@1@@2009,那我会说 - 好的。让我们使用 parseExact。但是那时我就不需要 culture 了。你能帮忙解决一下吗? - Royi Namir
@RoyiNamir:抱歉,我真的不明白你在问什么。 - Jon Skeet
@RoyiNamir:你可以使用任何一个,但我个人会使用“/”,因为任何阅读它的人都应该明白它是日期分隔符。 - Jon Skeet
显示剩余2条评论

3
我敢打赌你的机器文化不是“en-US”。从文档中可以看到:

如果提供者是空引用(在Visual Basic中为Nothing),则使用当前文化。

如果你的当前文化不是“en-US”,那就解释了为什么它适用于我,但对你不起作用,并且在显式指定文化为“en-US”时会起作用。

有趣的是,CultureInfo.CurrentCulture确实返回“en-us”...所以我不确定为什么它对你有效但对我无效。 - Jimmy
我尝试了几件事情,以下是有效的方法: DateTime.ParseExact("9/1/2009", "M'/'d'/'yyyy", null); DateTime.ParseExact("9/1/2009", "M/d/yyyy", CultureInfo.InvariantCulture);
DateTime.Parse("9/1/2009", new CultureInfo("en-US"));以下是无效的方法: DateTime.ParseExact(dateString, "M/d/yyyy", CultureInfo.CurrentCulture); DateTime.ParseExact(dateString, "M/d/yyyy", new CultureInfo("en-US")); DateTime.ParseExact(dateString, "M/d/yyyy", null); 所以Parse()可以在"en-US"下工作,但ParseExact不行...有趣吧?
- Jimmy

2

请尝试

Date.ParseExact("9/1/2009", "M/d/yyyy", new CultureInfo("en-US"))

我想如果我必须指定文化,我宁愿使用DateTime.Parse("9/1/2009", new CultureInfo("en-US")),对吧? - Jimmy
不要每次解析日期时都实例化一个新的CultureInfo("en-US")实例,而是使用CultureInfo.InvariantCulture。 - Joe
实际上这并不起作用(至少对我来说是这样的?)使用“en-US”可以与Parse一起使用,但不能与ParseExact(对于此日期和格式字符串)一起使用。 - Jimmy

0

试一下这个

provider = new CultureInfo("en-US");
DateTime.ParseExact("9/1/2009", "M/d/yyyy", provider);

再见。


-1

我在XP上尝试过,如果PC设置为国际时间yyyy-M-d,则无法正常工作。在该行上放置断点,并在处理之前将日期字符串更改为使用'-'代替'/',您会发现它可以正常工作。无论您是否拥有CultureInfo都没有任何区别。 似乎很奇怪能够指定预期格式,但分隔符被忽略。


-4
将 DateTimePicker 的 Format 属性设置为自定义,并将 CustomFormat 属性设置为 M/dd/yyyy。

1
这个问题与DateTimePicker完全无关。 - B.K.

-4

这个问题中没有任何暗示是一个网络应用程序。 - Ben Voigt

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