sql >> データベース >  >> RDS >> Mysql

mysqlとjavaのTimeZoneの不一致

    背景:驚くほど一般的で大きな誤解は、優秀なプログラマーでさえも共有されています。これは、タイムスタンプ(データベース、日付、カレンダー、タイムスタンプなど)に保存されたタイムスタンプが何らかの形でタイムゾーン情報を持っているという概念です。 そうではありません。 タイムスタンプ(とにかくJava 8まで)は、1970年1月1日UTCの午前0時からのミリ秒数として保存されます。文末。タイムゾーンを設定する唯一のことは、そのタイムスタンプを人間が読める形式に変換するのに十分な情報をコンピュータに提供することです。その逆も同様です。

    回答:これがタイムゾーンの問題であると思われる場合は、正しかった 。ただし、これを確認するために使用したコードにも問題があります。

    end.setTimeZone(TimeZone.getTimeZone("America/New York"));
    pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));
    

    そのsetTimeZone ステートメントには効果はありません endに保存された時間 、時刻がすでに設定されているため。後で時間を保存した場合にのみ効果があり、その後、人間が読める形式(setTimeInMillisではなく)から時間を変換するCalendarのメソッドの1つを使用した場合にのみ効果があります。 。

    getTimeInMillisを使用する場合 プリペアドステートメントにタイムスタンプを渡すには、タイムスタンプを直接取得します。人間の形式に変換していないため、タイムゾーン情報は無視されます。

    試してみると

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    end.setTime(sdf.parse("2012-10-01 00:00:00"));
    pst.setTimestamp(1, new java.sql.Timestamp(end.getTime()));
    

    および

    pst.setTimestamp(1, new java.sql.Timestamp(octDate.get(Calendar.YEAR)-1900,octDate.get(Calendar.MONTH),octDate.get(Calendar.DATE),octDate.get(Calendar.HOUR),octDate.get(Calendar.MINUTE),octDate.get(Calendar.SECOND),0));
    pst.setTimestamp(2, new java.sql.Timestamp(end.get(Calendar.YEAR)-1900,end.get(Calendar.MONTH),end.get(Calendar.DATE),end.get(Calendar.HOUR),end.get(Calendar.MINUTE),end.get(Calendar.SECOND),0));
    

    物事は現れる 人間が読める形式との間で変換するメソッドを使用しているため、機能します。したがって、指定されたタイムゾーン情報が使用されます。ただし、これは実際の問題をカバーしているだけです。本当の問題は、endStringから解析したときに、時刻が不適切に変換されたことです。 。つまり、endStringのタイムゾーンです。 で表現されたがdf1で設定されたタイムゾーンと一致しません 日付が解析されたとき。

    短い答え:この行の前:

    end.setTime(df1.parse(endString));
    

    次のことを行う必要があります:

    • endStringで時刻を把握するタイムゾーン で表現されました。
    • df1を設定します およびない end その同じタイムゾーンに。 df1以降 日付を人間の形式から変換するものであり、使用されるのはそのタイムゾーン情報です。

    乾杯!



    1. データベースの主キーは整数である必要がありますか?

    2. SQLクエリ

    3. SQLJOIN多対多

    4. byteaとして取得されたPostgreSQLJDBCNull文字列