2

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タイムゾーンで実行されています。Python 3.1 と openjdk 6 を使用して Debian 6.0.5 で PostgreSQL 8.4.11 を使用しています。

4

3 に答える 3

6

1333436817 * 1000 の結果は整数としては大きすぎるため、オーバーフローします。この場合、Java は型を自動的にプロモートしません。

それを試してください:

    c.setTimeInMillis(1333436817 * 1000L);

L計算で long integer を使用するように強制することに注意してください。

于 2012-05-28T06:14:50.030 に答える
1

ティボさんの回答は正しいです。私の追加の考えは続きます。

使用するTIMESTAMP WITH TIME ZONE

TIMESTAMP WITHOUT TIME ZONEPostgres でのデータ型の使用について言及しました。そのタイプは、特定のタイムゾーンに関連付けられていない日時専用です。たとえば、「クリスマスは 2015 年 12 月 25 日の午前 0 時に始まります」は、特定のタイム ゾーンの別の瞬間に変換されます。たとえば、クリスマスはモントリオールよりもパリの方が早く始まります。このデータ型は、ビジネス アプリではほとんど適切ではありません。この 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 によって文字列が生成されないため、そのセッション設定は関係ありません。タイム ゾーンへの注意は、Postgres ではなく Java 側に向ける必要があります (以下のコードを参照)。

一般的に言えば、ホスト サーバーのオペレーティング システムは UTC に設定する必要があります。ただし、アプリのコードはそれに依存するべきではなく、希望する/予想されるタイム ゾーンを指定する必要があります。

java.time

Java 8 以降では、新しい java.time パッケージが古い java.util.Date/.Calendar クラスに取って代わります。これらの新しいクラスは、JSR 310 で定義された Joda-Time ライブラリに触発され、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エポックからの秒数を指定して、Instant を作成します。

long secondsSinceUnixEpoch = 1_333_436_817L ;
Instant instant = Instant.ofEpochSecond( secondsSinceUnixEpoch );
ZoneId zoneId = ZoneId.of( "Asia/Tehran" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
于 2015-08-16T08:23:55.233 に答える
-2

Java Date ライブラリは設計が悪く、機能的ではありません。私はあなたの問題を解決することはできませんが、Joda カレンダーを試すようにアドバイスすることはできます

于 2012-05-28T06:13:22.627 に答える