Java 从UNIX时代创建日历的日期不正确(1970年的某个时间)?
我有一个存储unix时间和等效时间戳的表Java 从UNIX时代创建日历的日期不正确(1970年的某个时间)?,java,datetime,Java,Datetime,我有一个存储unix时间和等效时间戳的表 CREATE TABLE tbl_time ( time_unix BIGINT, time_timestamp TIMESTAMP WITHOUT TIME ZONE ); 数据库使用PostgreSQL。数据库已配置为亚洲/德黑兰时区。 例如: 1333436817, 2012-04-03 11:36:57 当我使用以下命令将unix时间转换为python中的字符串格式时: datetime.datetime.fromtimest
CREATE TABLE tbl_time
(
time_unix BIGINT,
time_timestamp TIMESTAMP WITHOUT TIME ZONE
);
数据库使用PostgreSQL。数据库已配置为亚洲/德黑兰
时区。
例如:
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
。系统本身在亚洲/德黑兰
时区下运行。我在Debian 6.0.5上使用PostgreSQL 8.4.11,使用python 3.1和openjdk 6。有人能帮忙吗?java日期库的设计很糟糕,没有那么好的功能。我无法真正帮助您解决问题,但我可以建议您尝试一下1333436817*1000的结果对于整数来说太大,因此溢出。在这种情况下,Java不会自动为您升级该类型
试试看:
c.setTimeInMillis(1333436817 * 1000L);
请注意,L
迫使您的计算使用长整数。由tibo编写是正确的。我的其他想法如下
将时间戳与时区一起使用
您提到在Postgres中使用不带时区的数据类型TIMESTAMP
。该类型仅适用于与任何特定时区无关的日期时间。例如,“2015年12月25日午夜开始的圣诞节”在任何特定时区都意味着不同的时刻。例如,巴黎的圣诞节比蒙特勒尔早。这种数据类型在商业应用程序中很少适用。请参阅此Postgres专家帖子
在Postgres中,另一种类型的带有时区的时间戳表示“关于时区”。与UTC或时区信息的任何偏移以及传入数据都用于调整到UTC。然后,将丢弃伴随的偏移量或时区信息。有些数据库保存这些信息,但不保存Postgres
你的声明:
数据库使用PostgreSQL。数据库已配置亚洲/德黑兰时区
…毫无意义。数据类型不带时区的时间戳
没有时区(尽管您可以将其视为UTC),并且数据类型带时区的时间戳
始终处于活动状态。关于存储日期时间值,没有这样的时区配置
您可能的意思是,数据库会话的默认时区设置为德黑兰时区。请参阅命令。但该设置只是粉饰,在生成日期时间值的字符串表示形式时应用。当使用JDBC和java.sql.Timestamp类时,该会话设置是不相关的,因为Postgres没有生成任何字符串。您对时区的关注应该放在Java端(参见下面的代码),而不是Postgres
一般来说,主机服务器操作系统应设置为UTC。但你的应用程序代码永远不应该依赖于此,而应该指定任何期望/预期的时区
java.time
在Java8和更高版本中,新的Java.time包取代了旧的Java.util.Date/.Calendar类。这些新类的灵感来自JSR310定义的Joda时间库,并通过项目进行了扩展
最终,JDBC驱动程序将被更新以直接处理这些新类型。同时使用添加到新旧类中的转换方法
java.sql.Timestamp ts = myResultSet.getTimestamp( 1 );
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
或者根据你从纪元算起的整秒数,构造一个瞬间
long secondsSinceUnixEpoch = 1_333_436_817L ;
Instant instant = Instant.ofEpochSecond( secondsSinceUnixEpoch );
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
请不要再说了!图书馆并不完美,但我从来没有遇到过问题,我可以做我想做的每一件事。你的回答与这些问题无关。。。