我有一台服务器正在从不同时区的客户端提供数据。数据Feed包含人员,他们的出生日期和其他事件日期。出于我们的目的,如果我们可以将日期存储给我们,那将会很方便。
例如,如果客户在加利福尼亚并告诉我们该人的出生日期是5月31日,我们希望将其存储在1999年5月31日太平洋时间的数据库中。这样,无论你在哪个时区,你都可以看到这个人出生在5月31日。
与此同时,我们希望能够查询这些数据,以便能够找出诸如“这个人是未成年人”或“这个事件是否在24小时前发生?”这样的事情?
客户端通过基于http的rest API向我们发送数据。服务器是用Java编写的(使用eclipselink)。数据库是postgresql。是否有可能满足这些要求?
通常,人们会说将所有内容都存储为UTC,但我觉得这样做不是一个好主意,因为我们会丢失原始数据的时区。
答案 0 :(得分:3)
UTC是要走的路。对于timestamptz
(timestamp with time zone
),输入值的时区仅用作Postgres内部计算UTC的修饰符。 (对于timestamp [without time zone]
,任何附加的时区都将被忽略!)。时区未保存。您需要另外保存以了解世界上发生的事情。
如果您这样做,您也可以存储本地时间戳。只是不要混淆哪个是哪个。将所有内容转换为UTC(自动为timestamptz
发生),或将所有内容转换为本地时间(定义“本地”:本地?本地到数据库服务器?本地用户?)。
特别是,存储确切的时区名称(或对其的引用)而不仅仅是“太平洋时间”。对于夏令时,闰秒或其他事件,这更为准确。
详细说明:
关于时区名称和缩写:
关于时区处理:
答案 1 :(得分:2)
answer by Erwin Brandstetter 100%正确。
关于计算未成年人年龄的事项,因为一天中的时间而有点棘手。使用Joda-Time库,您可以调用方法withTimeAtStartOfDay
将DateTime对象设置为当天的第一个时刻。通常第一个时刻是时间00:00:00
,但并不总是因为夏令时或其他异常。忽略与上述方法取代的“午夜”相关的类和方法。
此外,为了真正准确地了解年龄以合法地覆盖自己,您可能希望将年龄计算为一天中的第一个时刻或 出生日期时间之后的。除非你知道他们的出生时间和出生的时区,否则你无法准确知道他们的年龄。
与Java捆绑在一起的java.util.Date和.Calendar类非常麻烦。避免他们。使用Joda-Time和/或java.time package中捆绑的新Java 8(受Joda-Time启发,但重新设计)。
与java.util.Date不同,其他库中的日期时间对象都知道自己分配的时区。 j.u.Date特别令人困惑,因为虽然它没有分配时区,但它的toString
方法应用了JVM当前的默认时区,从而产生了指定时区的错觉。
使用Joda-Time和java.time,事情会更加清晰。您为每个日期时间对象指定时区(否则分配JVM默认值)。您可以轻松地从一个时区转换为其他时区。
两个库都使用immutable objects,其中创建了基于原始对象的新对象,而不是更改(变异)原始对象。
如果您认为重要,可以拨打getZone
Joda-Time DateTime
对象获取its time zone name (ID)及其与UTC的偏移量。
了解日期时间值的敏感字符串格式的ISO 8601标准。考虑在基于文本的API中使用它们。 ISO 8601现在已成为所有新互联网协议的标准。例如:2014-08-13T16:02:01Z
或2014-12-22T11:54:23+04:00
。
并使用proper time zone names。避免使用3或4个字母代码,因为它们既不标准也不唯一。