使用其他文化时错误的 DateTime 解析

Posted

技术标签:

【中文标题】使用其他文化时错误的 DateTime 解析【英文标题】:Wrong DateTime parsing when using other cultures 【发布时间】:2016-03-24 21:43:18 【问题描述】:

我在多语言站点中使用 EF 将结果从 SP 映射到对象。

ctx.Database.SqlQuery<MyDTO>("MySP 0", Id).SingleOrDefault()

我发现当文化发生变化时映射日期存在问题。

更具体地说,我得到与16/12/2015 09:06:1512/16/2015 09:06:15 相同的日期,具体取决于用户文化。

我知道两种解决方案:

以字符串形式获取日期并使用CultureInfo.InvariantCulture 进行解析。 在调用存储库方法之前将区域性切换为 CultureInfo.CultureInvariant

也许还有另一种选择:

我看到我们将Thread.CurrentThread.CurrentUICultureThread.CurrentThread.CurrentCulture 都更改为用户的区域设置,但我认为我们应该只切换UI 之一。但我不确定如果我改变它会破坏什么......

有没有其他选择,比如在 EF 上下文中设置文化?


更新: 在进行查询之前更改Thread.CurrentThread.CurrentUICultureThread.CurrentThread.CurrentCulture 似乎也无济于事。这令人困惑……也许 EF 在更早的时候缓存了文化?

【问题讨论】:

如果您始终将日期时间数据视为日期时间数据,则应该没有问题。只有将数据转换为 strings 时才会出现格式问题。 避免尽可能多的转化。那么,你一开始是怎么得到像12/16/2015 09:06:15 这样的字符串的呢? @Damien_The_Unbeliever 你好。我最终弄清楚了这一点。 :) 我没有使用字符串,我只是在手表中查看DateTimes 的值。这实际上是问题所在......看起来手表使用当前线程的文化。事实证明日期是正确的(这:12/16/2015 09:06:15 无论如何都不是有效的日期......永远不会太迟意识到......:D)。该错误后来出现在代码中。我将在下面发布答案。 【参考方案1】:

首先,您应该避免这样调用您的存储过程 - 这是解决OWASP Top 10 Sql Injection 安全问题的简单方法。

相反,您应该通过将参数作为实际参数传递给存储过程来调用,例如:

string dateAsString = "12/16/2015 09:06:15";
string dateFormat = "MM/dd/yyyy HH:mm:ss";
DateTime theValue = DateTime.Parse(dateAsString, dateFormat, CultureInfo.InvariantCulture);
SqlParameter myDate = new SqlParameter("@theDate", theValue);
context.Database.ExecuteSqlCommand("MySP @theDate", theDate);

【讨论】:

我的印象是ctx.Database.SqlQuery 是为了防止SQL 注入而设计的,它与String.Format 不同。我认为 MS 将如此冒险的东西放入 EF 会非常天真。你确定我的方法真的有问题吗? 例如,请参见此处:***.com/a/17861166/2173353(我希望我能在 MSDN 中找到一个关于此的示例...)。 我现在没有时间测试它,我个人在将参数传递给 ORM 之前尽我所能,以防万一......无论如何,不​​管是否存在安全问题,解析日期并将其作为参数传递应该可以解决此答案中提供的问题...【参考方案2】:

您可以将日期时间存储为长(柚木)或实数(将日期时间转换为实数时获得的数字)。然后,您可以将这些值转换为任何文化而不会造成任何损失。

【讨论】:

谢谢,但我无法更改数据库。 :)【参考方案3】:

我终于想通了。 :)

我在手表中查看DateTimes 的值。这实际上是问题所在......看起来手表使用当前线程的文化(从而将月份和日期的顺序从文化切换到文化)。结果证明日期是正确的(如果您认为 16 是一个月,12/16/2015 09:06:15 无论如何都不是有效日期......永远不会太迟意识到......)。

所以,VS 观察者让我迷失了方向......

很高兴知道当前的线程文化不会像我所期望的那样影响 SQL 数据的解析。 :)

实际的错误出现在代码中。

【讨论】:

以上是关于使用其他文化时错误的 DateTime 解析的主要内容,如果未能解决你的问题,请参考以下文章

MVC 控制器接收从 CurrentThread.CurrentCulture 解析为不同文化的 DateTime

为啥不管文化如何,C# DateTime 解析“01/05/2020”都是一样的?

.NET 4.5 DateTime 格式/转换错误与上索布文化

无论文化信息如何,C# 解析为日期时间

DateTime 格式没有正确的文化 WP8

实体框架中的日期时间文化问题