Java 为什么时间戳不存储在UTC时间?

Java 为什么时间戳不存储在UTC时间?,java,postgresql,timezone,jodatime,jooq,Java,Postgresql,Timezone,Jodatime,Jooq,我有一个store\u time\u period,应该有两个带时区的时间戳。我正在使用jodaorg.joda.time.DateTime而不是java.sql.Timestamp,我正在初始化变量,例如: DateTime day_from = new DateTime(DateTimeZone.UTC); 然而,在phpPgAdmin中,我看到的是以下字符串: 2016-01-06 20:14:09.339+01 而不是 2016-01-06 19:14:09.339+00 UTC时间。

我有一个
store\u time\u period
,应该有两个带时区的
时间戳。我正在使用joda
org.joda.time.DateTime
而不是
java.sql.Timestamp
,我正在初始化变量,例如:

DateTime day_from = new DateTime(DateTimeZone.UTC);
然而,在phpPgAdmin中,我看到的是以下字符串:

2016-01-06 20:14:09.339+01

而不是

2016-01-06 19:14:09.339+00

UTC时间。为什么会这样

这就是我如何转换
日期时间
时间戳

public class JodaDateTimeConverter implements Converter<Timestamp, DateTime> {
    @Override
    public DateTime from(Timestamp timestamp) {
        DateTime dateTime = new DateTime(timestamp.getTime());
        return dateTime;
    }

    @Override
    public Timestamp to(DateTime dateTime) {
        Timestamp timestamp = new Timestamp(dateTime.getMillis());
        return timestamp;
    }

    @Override
    public Class<Timestamp> fromType() {
        return Timestamp.class;
    }

    @Override
    public Class<DateTime> toType() {
        return DateTime.class;
    }
}

此行为符合带时区的时间戳的定义,来自:

对于带有时区的时间戳,内部存储的值始终处于 UTC(世界协调时间),传统上称为格林威治标准时间 时间(格林尼治标准时间)。指定了具有显式时区的输入值 使用该时区的适当偏移量转换为UTC。如果 输入字符串中未说明时区,则假定为 在系统时区参数指示的时区中,并且 使用时区的偏移量转换为UTC

当输出带有时区值的时间戳时,总是 从UTC转换为当前时区,并显示为 该区域的本地时间。在另一个时区查看时间 更改时区或使用AT时区结构(见第9.9.3节)


在你的代码中,当你构造一个
DateTime
时,你正在使用一个接受
long
时间戳的构造函数。时间戳本身是基于UTC的,尽管在postgres中使用带时区的时间戳,因为postgres不存储时区

那个特定的构造器说:

使用默认时区中的
ISOChronology
构造一个实例集,设置为从
1970-01-01T00:00:00Z
开始的毫秒数

关键是当您不指定时区时,将使用默认时区(系统的本地时区或您显式设置的时区)


如果可以使用其他方法(可能存储在应用程序或数据库的其他位置)确定时区,则可以使用。

这是JDBC和数据库级别的问题。您正在
转换器上使用
java.sql.Timestamp
作为
类型。jOOQ将把这个时间戳绑定到JDBC,JDBC指定
timestamp
是您的本地时间

请注意,jOOQ的代码生成器尚未完全支持带时区的时间戳。这是一个挂起的功能请求:


如果您想绑定joda-time的
DateTime
,您必须自己使用一个来实现JDBC级别的绑定。这样,您就可以完全控制发送到服务器和从服务器检索的内容。

我既不是PostgreSQL的专家,也不是phpPgAdmin的专家。但我想的是,要么将phpPgAdmin设置为显示本地时间,要么将PostgreSQL设置为存储本地时间。您可以通过使用命令行连接(如果存在)或再次使用java代码来检查PostgreSQL。它可能存储在UTC中。当你查看它时,你只是看到它被转换成一个时区。@MattJohnson,但为什么它不将它转换回我存储它的时区呢?我无法想象phpPgAdmin只是将每个时间戳转换为我的本地时间。为什么会这样?但我会试试,它不储存时区。它在检索时使用会话时区。(如果您习惯于SQL Server中的
datetimeoffset
,它会存储偏移量-这是不同的行为。)实际上-不必指定会话时区。有时候是这样,但对你来说,有一个更简单的答案。我很快会写一个答案……嗯,但是我在UTC时区中创建了一个
DateTime
DateTime day\u from=new DateTime(DateTimeZone.UTC)
@Stefan:您可能假设它应该将这个时区与datetime一起存储,然后在您读回该列时将其原封不动地返回。由于类型的名称,这是一个常见的误解,但现在它就是这样工作的。输入时区只用于计算UTC值,然后它就丢失了。好吧,这太奇怪了。所以我想要一个带有时区的
时间戳
,但我得到的是一个UTC时间戳,它被转换为机器运行的当前时区,正如它在“它总是从UTC转换为当前时区,并在该时区中显示为本地时间”中所说的那样?因为那绝对不是我想要的。如果我把UTC放在^ ^ @斯特凡中,我想得到UTC:考虑“代码”>没有时区< /代码>的时间戳(如果您只对UTC感兴趣),或者如果您希望保留原始时区或偏移到GMT,则需要添加单独的列来存储它。
CREATE TABLE store_time_period (

    -- PRIMARY KEY

    id BIGSERIAL PRIMARY KEY,

    -- ATTRIBUTES

    day_from TIMESTAMP WITH TIME ZONE NOT NULL, 
    day_to TIMESTAMP WITH TIME ZONE NOT NULL
);