使用“+”符号的DateTime.Parse

4
我有一段代码,用于解析和验证用户输入:
DateTime myDateTime = DateTime.Parse(userInput,currentCulture);

当前的区域设置为en-ca或fr-ca,并且用户输入始终以ISO 8601格式"yyyy-MM-dd"表示。

如果用户输入1900-01-01,则日期将按预期创建。如果输入为"1900-01+01",则创建的日期时间为1899-12-31 6:00:00 PM。不会抛出异常,DateTime.Parse会愉快地将其转换为错误的日期。

为了使其正常工作,我使用DateTime.ParseExact(userInput,"yyyy-MM-dd",currentCulture)

所以我的问题不是如何使其正常工作(我已经解决了),而是+01或任何+值有什么问题?我是否在ISO标准中漏掉了什么东西?


2
你认为'1900-01+01'应该解析成什么?你是说这是一个有效的日期吗? - Adrian Thompson Phillips
在解析日期时间之前,您可以将“+”替换为“-”。 - Asif Mushtaq
1
最好进行客户端和服务器端验证,以验证您的日期格式是否为“yyyy-MM-dd”,否则显示错误。 - Adrian Thompson Phillips
不,我并不是说这是一个有效的日期,恰恰相反。它不应该被解析,但它却被解析成了一个日期。 - THBBFT
那么在这种情况下,您需要做的是在将用户输入放入任何解析算法之前对其进行验证。 - Adrian Thompson Phillips
这是验证的一部分。另外,重构代码时,原来的代码使用try块来失败验证,而不是使用TryParseExact。 - THBBFT
1个回答

4
在 ISO8601 中,唯一的 + 出现在时间偏移部分,看起来在这种情况下是按这种方式解析的。但据我所知,在允许使用时间偏移之前,日期的所有 3 个部分都必须具有有效值。
我建议使用 DateTime.ParseExact(userInput,"yyyy-MM-dd",...)(甚至带上InvariantCulture)。
DateTime.Parse 接受各种输入并尝试根据用户意图做出最佳猜测。这感觉就像是一个简单混乱的猜测。
示例值(第一个为本地PDT,其他两个带有显式时间偏移):
DateTime.Parse("1900-02"   ).ToUniversalTime()    //  2/ 1/1900  8:00:00 AM 
DateTime.Parse("1900-02+00").ToUniversalTime()    //  2/ 1/1900 12:00:00 AM
DateTime.Parse("1900-02+03").ToUniversalTime()    //  1/31/1900  9:00:00 PM

似乎Parse"YYYY-MM+0x"视为"YYYY-MM-01T00:00+0x"

是的,我目前正在使用带有区域性的ParseExact,并且即将使用TryParseExact来消除冗余的try-catch语句(老实说,这是别人的代码味道)。关于最佳匹配/猜测的问题,你说得很好。 - THBBFT
如果“+”表示时间偏移量(我的第一反应也是如此),那么日期不应该变大吗?它回溯了6个小时。 - THBBFT
1
@Blah_Blah,偏移是以协调世界时(UTC)为基准的。我已经在答案中放置了一些示例值,希望能够消除一些困惑。例如,你的时区偏移是"+06",而我的是"-08" - 所以对于Parse("1900-02")我们将会得到非常不同的结果。 - Alexei Levenkov
是的,我刚刚也遇到这个问题了,幸运的是我先刷新了一下。将ParseExact加入最佳实践列表中... - THBBFT

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