我和我的同事在一场辩论中陷入僵局,非常感谢其他人的意见。
我们利用服务定位器模式和一个公共接口来抽象所有的数据访问,这样我们就可以在需求变化时轻松地在不同的数据源之间进行交换。我们的调用代码没有指示数据存储在哪里或如何存储。它只是通过服务注册中心提供的服务来访问数据。
当我们在对象上有DateTime字段并将其存储到MongoDB数据源时,我们正在讨论的问题发生了。
我注意到的是,当我们在c#中有一个带有DateTime的对象时,它显示为正确的时间。当我们用MongoVUE登录到MongoDB服务器来检查对象时,它会显示正确的时间。但是当我们检索对象时,DateTime现在是UTC格式。这显然会在比较内存中的DateTime与从MongoDB数据源检索的对象中的DateTime时产生问题。
我知道Mongo内部存储DateTime作为UTC时间。我甚至理解为什么当你调用它时它可能返回UTC。
辩论从这里开始。
有人认为这只是一个外观问题,只有在显示日期时才会出现问题。因此,我们应该简单地在接口层中调用。tolocaltime。我不同意并断言,这危险地破坏了我们在实现服务定位器模式时创建的抽象层。它还提出了与这些日期时间交互的问题,因为它涉及触发其他事件。
我在其他地方读到的是,我们应该将时间存储为字符串,特别是作为UTC格式的一些标准。通过这种方式,接口层不知道或不关心DateTime是如何存储的,我们的对象也不知道,因为每个数据源都会以相同的方式存储该字符串。
我使用ISO 1806格式成功地做到了这一点,但我的同事觉得这是一个"黑客"修复,使用。tolocaltime是处理这种情况的适当方法。
我对别人对这个话题的看法很感兴趣。提前感谢您的意见
为什么不首先将UTC存储在DB中?在大多数情况下,DateTime
应该存储在UTC中,因为它通常指的是一个时间点。这适用于任何物理意义上的时间,以及任何假设时间是单调的、递增的和唯一的,而对于大多数本地时间来说,这些都不成立。
偶尔,使用当地时间是有意义的:假设一辆公共汽车每天早上9点离开。这意味着两个连续事件之间间隔24小时。但是,如果时区有夏令时,则每年一次为23小时,分别为25小时的间隔。
然而,如果你需要处理这类数据,一个简单的DateTime
并不能解决问题;DST规则可以改变,时区可以改变,等等。在c#中,将应用的DST规则是那些当前有效的规则,即使日期是"历史的"。因此,具有历史日期的日期算法可能造成严重破坏。如果您确实需要处理这个问题,至少应该存储时间所在的时区(不仅仅是偏移量,甚至只是isLocal
标志)。
在数据库中存储可以以二进制形式存储的文本信息对我来说似乎不是很优雅,在某些中间层中更改值也不是很优雅。前者效率低下,且存在前面提到的本地时间特性,后者只有第二个问题。
顺便说一句,要完成后者,您可以使用[BsonDateTimeOptions(Kind=DateTimeKind.Local)]
装饰属性,它将为您完成转换,但当然也会遇到同样的问题。