2

之前有个类似的话题:夏令时和时区最佳实践

我想问的是相关的,但不同的。

日期处理的建议做法是什么?

我正在寻找一个更“合乎逻辑”的日期。例如,我们申请的营业日期,或某些人的出生日期。

通常我将它存储为日期(在 Oracle 中),时间为 0:0:0。如果我的应用程序的所有组件都在同一个时区,这将正常工作。因为数据库中的日期意味着数据库时区的 0:0:0,如果我将我的数据呈现给另一个时区的用户,它很容易出现问题,因为例如,日期 2012-12-25 0:0:0伦敦时间实际上是香港时间 2012-12-24 16:0:0。

我想了两种方法来解决,但它们都有其不足之处。

首先,我们将其存储为字符串。缺点很明显:我需要在我们的应用程序或查询中进行大量对话,并​​且丢失了很多日期算术

第二种方法是将其存储为日期,但具有预定义的时区(例如 UTC)。当应用程序显示日期时,它必须显示为 UTC 时区。但是,我需要在我的应用程序代码中进行大量时区操作。

处理日期的建议方法是什么?还是大多数人只是使用上述 3 种方法中的一种(包括假设为相同时区的方法)?

4

3 回答 3

2

在任何地方使用 UTC 使事情变得简单和一致。将日期(作为时间点)保存为数据库中的 UTC,在 UTC 中对它们进行数学运算,仅在视图层中显式转换为本地时间,将用户输入日期转换为 UTC 将为您需要的任何操作或计算提供相当稳定的基础跟他们。您实际上并不需要以 UTC 向用户显示日期 - 实际上以本地时间显示它们并暗示您可以向它们显示 UTC 提供了更多有用的信息。
如果您只需要保留日期(例如生日,您在评论中提到的内容),请明确删除此类信息(例如在数据库级别从 DateTime 转换为 Date 或任何代码级别的可能性)。
这是良好规范化的示例 - 您在代码页上使用 UTF 或保持相同单位进行物理计算时所做的事情相同。
使用这种方法,不同日期的代码会简单得多。在显示 UTC 和本地人之间的日期和转换的情况下,许多框架(甚至语言本身)为您提供了处理本地人的工具,同时使用 UTC 等。

于 2012-12-10T05:47:43.707 回答
2

日期是一种标识一天的方式,一天是相对于当地的时区,也就是太阳。一天是 24 小时周期(尽管由于闰秒和其他恒星校正,24 小时只是一个非常接近的近似值)。因此,伦敦的 12 月 5 日日期与纽约的 12 月 5 日日期命名不同的 24 小时时段。这样做的后果之一是,如果您想对不同时区之间的日期进行算术运算,则只能达到 +/- 1 的精度。作为一种数据结构,这是一个传统的日期(例如,年份和天偏移量)和一个由与 UTC 的小时偏移量标识的时区(请注意,那里有一些 1/2 小时的偏移量)。

应该清楚的是,将一个时区的日期转换为另一个时区的日期是不可能的,因为它们代表不同的时间间隔。(大多数情况下。相邻时区可能有例外,一个是夏令时,一个不是。)出于同样的原因,不同时区之间的日期计算通常也不能完成。有时没有足够的数据来获得完美的答案。

但是,您提出的问题背后的问题的完整答案取决于日期的含义。例如,如果它们是诸如截止日期之类的合法日期,那么这些日期通常是相对于办公楼的位置来获取的,例如截止日期的计时地点。在这种情况下,日期边界遵循一个时区,冗余存储它是没有意义的。时间将在存储时转换为该时区的日期。

于 2012-12-06T01:20:22.347 回答
2

我曾经设计并领导构建了一个实时交易系统,该系统在多个时区处理客户,但都在一个时区的时间段内开具发票。

对我来说效果很好的解决方案是在每条记录上存储 UTC 时间和本地时间。这是在使用该系统几年后才意识到日期列确实有两种不同的用途,因此数据以这种方式存储。

尽管它在磁盘上多用了几个字节(大不了——磁盘很便宜),但它在查询时让事情变得如此简单;“临时”查询(例如搜索客户交易的帮助台)使用本地时间列,“正式”查询(例如会计部门发票批处理运行)使用 UTC 列。

它还处理了每次夏令时倒退一小时时本地时间“重温”一小时交易的问题,如果您是 24 小时营业的企业,那么仅使用本地时间会变得非常痛苦。

于 2012-12-11T18:28:00.303 回答