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

UTCでDATETIMEとTIMESTAMPを適切に処理するためのJDBC-mysqlドライバー設定とは何ですか?

    解決策は、JDBC接続パラメーターnoDatetimeStringSync=trueを設定することです。 useLegacyDatetimeCode=falseを使用 。ボーナスとして、sessionVariables=time_zone='-00:00'も見つかりました set time_zoneを設定する必要性を軽減します 新しい接続ごとに明示的に。

    ResultSet.getString()の奥深くでアクティブ化される「インテリジェントな」タイムゾーン変換コードがいくつかあります。 列がTIMESTAMPであることを検出したときのメソッド 列。

    残念ながら、このインテリジェントコードにはバグがあります:TimeUtil.fastTimestampCreate(TimeZone tz, int year, int month, int day, int hour, int minute, int seconds, int secondsPart) Timestampを返します tzの場合でも、JVMのデフォルトのタイムゾーンに誤ってタグ付けされている パラメータが別のものに設定されている:

    final static Timestamp fastTimestampCreate(TimeZone tz, int year, int month, int day, int hour, int minute, int seconds, int secondsPart) {
        Calendar cal = (tz == null) ? new GregorianCalendar() : new GregorianCalendar(tz);
        cal.clear();
    
        // why-oh-why is this different than java.util.date, in the year part, but it still keeps the silly '0' for the start month????
        cal.set(year, month - 1, day, hour, minute, seconds);
    
        long tsAsMillis = cal.getTimeInMillis();
    
        Timestamp ts = new Timestamp(tsAsMillis);
        ts.setNanos(secondsPart);
    
        return ts;
    }
    

    リターンts 呼び出しチェーンのさらに上位にある場合を除いて、完全に有効です。裸のtoString()を使用して文字列に変換されます。 tsをレンダリングするメソッド UTCでの時刻の文字列表現ではなく、JVMのデフォルトのタイムゾーンで時計が表示する内容を表す文字列として。 ResultSetImpl.getStringInternal(int columnIndex, boolean checkDateTypes)で :

                    case Types.TIMESTAMP:
                        Timestamp ts = getTimestampFromString(columnIndex, null, stringVal, this.getDefaultTimeZone(), false);
    
                        if (ts == null) {
                            this.wasNullFlag = true;
    
                            return null;
                        }
    
                        this.wasNullFlag = false;
    
                        return ts.toString();
    

    noDatetimeStringSync=trueを設定する 解析/解析解除の混乱全体を無効にし、データベースから受け取ったままの文字列値を返します。

    テスト出力:

    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    

    useLegacyDatetimeCode=false getDefaultTimeZone()の動作を変更するため、これは依然として重要です。 データベースサーバーのTZを使用します。

    これを追いかけていると、useJDBCCompliantTimezoneShiftのドキュメントも見つかりました。 違いはありませんが、正しくありません。ドキュメントには[これは従来の日時コードの一部であるため、プロパティは「useLegacyDatetimeCode=true」の場合にのみ有効です。 ]、しかしそれは間違っています。ResultSetImpl.getNativeTimestampViaParseConversion(int, Calendar, TimeZone, boolean)を参照してください。 。




    1. mySQL-utf8(英語以外)データへのラテン語(英語)フォーム入力のマッチング

    2. ScaleGridは2017-2018クラウドアワードプログラムの最終候補になりました

    3. 外部キーごとに限られた数の行を選択するにはどうすればよいですか?

    4. 重複する行を削除するにはどうすればよいですか?