使用其他文化时错误的 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:15
或12/16/2015 09:06:15
相同的日期,具体取决于用户文化。
我知道两种解决方案:
以字符串形式获取日期并使用CultureInfo.InvariantCulture
进行解析。
在调用存储库方法之前将区域性切换为 CultureInfo.CultureInvariant
。
也许还有另一种选择:
我看到我们将Thread.CurrentThread.CurrentUICulture
和Thread.CurrentThread.CurrentCulture
都更改为用户的区域设置,但我认为我们应该只切换UI 之一。但我不确定如果我改变它会破坏什么......
有没有其他选择,比如在 EF 上下文中设置文化?
更新:
在进行查询之前更改Thread.CurrentThread.CurrentUICulture
和Thread.CurrentThread.CurrentCulture
似乎也无济于事。这令人困惑……也许 EF 在更早的时候缓存了文化?
【问题讨论】:
如果您始终将日期时间数据视为日期时间数据,则应该没有问题。只有将数据转换为 strings 时才会出现格式问题。 避免尽可能多的转化。那么,你一开始是怎么得到像12/16/2015 09:06:15
这样的字符串的呢?
@Damien_The_Unbeliever 你好。我最终弄清楚了这一点。 :) 我没有使用字符串,我只是在手表中查看DateTime
s 的值。这实际上是问题所在......看起来手表使用当前线程的文化。事实证明日期是正确的(这: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】:我终于想通了。 :)
我在手表中查看DateTime
s 的值。这实际上是问题所在......看起来手表使用当前线程的文化(从而将月份和日期的顺序从文化切换到文化)。结果证明日期是正确的(如果您认为 16 是一个月,12/16/2015 09:06:15
无论如何都不是有效日期......永远不会太迟意识到......)。
所以,VS 观察者让我迷失了方向......
很高兴知道当前的线程文化不会像我所期望的那样影响 SQL 数据的解析。 :)
实际的错误出现在代码中。
【讨论】:
以上是关于使用其他文化时错误的 DateTime 解析的主要内容,如果未能解决你的问题,请参考以下文章
MVC 控制器接收从 CurrentThread.CurrentCulture 解析为不同文化的 DateTime
为啥不管文化如何,C# DateTime 解析“01/05/2020”都是一样的?