简体   繁体   中英

Incorrect date (sometime in 1970) when creating Calendar from UNIX epoch time?

I have a table which stores both unix time and the equivalent time stamp.

CREATE TABLE tbl_time
(
    time_unix BIGINT,
    time_timestamp TIMESTAMP WITHOUT TIME ZONE
);

The database is in PostgreSQL. database has been configured with Asia/Tehran time zone. for example:

1333436817, 2012-04-03 11:36:57

When I convert the unix time into string format in python with:

datetime.datetime.fromtimestamp(1333436817)

it gives me: datetime.datetime(2012, 4, 3, 11, 36, 57) which is correct and equal to database. But when I do this conversion with java using:

Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"));
c.setTimeInMillis(1333436817 * 1000);
System.out.println(c.getTime());

It gives: Sat Jan 24 06:12:35 IRST 1970 . The system itself is running under Asia/Tehran time zone. I'm using PostgreSQL 8.4.11 on Debian 6.0.5 with python 3.1 and openjdk 6. Can anyone help?

The result of 1333436817 * 1000 is too big for an integer so it overflows. Java will not promote the type for you automatically in this case.

Try that:

    c.setTimeInMillis(1333436817 * 1000L);

Notice the L that force your calculation to use long integer.

The Answer by tibo is correct. My additional thoughts follow.

Use TIMESTAMP WITH TIME ZONE

You mentioned using the data type TIMESTAMP WITHOUT TIME ZONE in Postgres. That type is only for a date-time not tied to any specific time zone. For example, "Christmas starts at midnight on December 25, 2015" translates to a different moment in any particular time zone. Christmas starts earlier, for example, in Paris than in Montréal. This data type is rarely appropriate in business apps. See this Postgres expert's post, Always use TIMESTAMP WITH TIME ZONE .

In Postgres, the other type TIMESTAMP WITH TIME ZONE means "with respect for time zone". Any offset from UTC or time zone information with incoming data is used to adjust to UTC. That accompanying offset or time zone info is then discarded. Some databases preserve this info, but not Postgres.

Your statement:

The database is in PostgreSQL. database has been configured with Asia/Tehran time zone.

…makes no sense. The data type TIMESTAMP WITHOUT TIME ZONE has no time zone (though you may regard it as UTC), and the data type TIMESTAMP WITH TIME ZONE is always in UTC . With regard to storing date-time values, there is no such time zone configuration.

What you may have meant is that the default time zone for a database session is set to Tehran time zone. See the SET TIME ZONE command. But that setting is mere window-dressing, applied when generating a string representation of the date-time value. When using JDBC and the java.sql.Timestamp class, that session setting is irrelevant as no Strings are being generated by Postgres. Your attention to time zones should be on the Java side (see code below) rather than Postgres.

Generally speaking, your host server operating system should be set to UTC. But your app's code should never depend on that, instead specifying any desired/expected time zone.

java.time

In Java 8 and later, the new java.time package supplants the old java.util.Date/.Calendar classes. These new classes were inspired by Joda-Time library, defined by JSR 310, and extended by the ThreeTen-Extra project.

Eventually JDBC drivers will be updated to directly handle these new types. In the mean time use the conversion methods added to both the old and new classes.

java.sql.Timestamp ts = myResultSet.getTimestamp( 1 ); 
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Or given your count of whole seconds from the Unix Time epoch, construct an Instant.

long secondsSinceUnixEpoch = 1_333_436_817L ;
Instant instant = Instant.ofEpochSecond( secondsSinceUnixEpoch );
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

The java Date library has a bad design and not that functional. I can't really help you with your problem but i can give you an advice to try Joda calendar

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM