我有一个存储unix时间和等效时间戳的表。
CREATE TABLE tbl_time
(
time_unix BIGINT,
time_timestamp TIMESTAMP WITHOUT TIME ZONE
);
数据库在PostgreSQL中。数据库已配置Asia/Tehran
时区。
例如:
1333436817, 2012-04-03 11:36:57
当我使用以下命令将unix时间转换为python中的字符串格式时:
datetime.datetime.fromtimestamp(1333436817)
它给了我:datetime.datetime(2012, 4, 3, 11, 36, 57)
这是正确的,等于数据库。但是当我使用java进行这种转换时:
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"));
c.setTimeInMillis(1333436817 * 1000);
System.out.println(c.getTime());
它给出:Sat Jan 24 06:12:35 IRST 1970
。系统本身在Asia/Tehran
时区下运行。我在Debian 6.0.5上使用PostgreSQL 8.4.11和python 3.1以及openjdk 6.有人可以帮忙吗?
答案 0 :(得分:6)
1333436817 * 1000的结果对于整数来说太大了,所以它会溢出。在这种情况下,Java不会自动为您提升类型。
试试:
c.setTimeInMillis(1333436817 * 1000L);
请注意L
强制您的计算使用长整数。
答案 1 :(得分:1)
TIMESTAMP WITH TIME ZONE
您提到在Postgres中使用数据类型TIMESTAMP WITHOUT TIME ZONE
。该类型仅适用于与任何特定时区无关的日期时间。例如,“圣诞节从2015年12月25日午夜开始”转换为任何特定时区的不同时刻。例如,圣诞节开始于巴黎,而不是蒙特利尔。此数据类型很少适用于商业应用。请参阅Postgres专家的帖子Always use TIMESTAMP WITH TIME ZONE。
在Postgres中,另一种类型TIMESTAMP WITH TIME ZONE
表示“尊重时区”。 UTC或带有传入数据的时区信息的任何偏移都用于调整为UTC。然后丢弃伴随的偏移或时区信息。有些数据库保留了这些信息,但不保留Postgres。
您的陈述:
数据库在PostgreSQL中。数据库已配置亚洲/德黑兰时区。
......毫无意义。数据类型TIMESTAMP WITHOUT TIME ZONE
没有时区(尽管您可能将其视为UTC),数据类型TIMESTAMP WITH TIME ZONE
始终位于UTC。关于存储日期时间值,没有这样的时区配置。
您可能意味着数据库会话的默认时区设置为德黑兰时区。请参阅SET TIME ZONE
命令。但是,该设置仅仅是一种装饰,在生成日期时间值的字符串表示时应用。使用JDBC和java.sql.Timestamp类时,该会话设置无关紧要,因为Postgres不生成任何字符串。您对时区的关注应该在Java端(参见下面的代码)而不是Postgres。
一般来说,您的主机服务器操作系统应设置为UTC。但是,您的应用代码永远不应该依赖于此,而是指定任何所需/预期的时区。
在Java 8及更高版本中,新的java.time包取代了旧的java.util.Date/.Calendar类。这些新类的灵感来自Joda-Time库,由JSR 310定义,并由ThreeTen-Extra项目扩展。
最终将更新JDBC驱动程序以直接处理这些新类型。同时使用添加到旧类和新类的转换方法。
java.sql.Timestamp ts = myResultSet.getTimestamp( 1 );
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
或者从Unix Time时代开始计算整秒数,构建一个瞬间。
long secondsSinceUnixEpoch = 1_333_436_817L ;
Instant instant = Instant.ofEpochSecond( secondsSinceUnixEpoch );
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
答案 2 :(得分:-2)
java Date库设计不好而且功能不强。我无法真正帮助你解决问题,但我可以给你一个建议,试试Joda calendar