Mysql
 sql >> база данни >  >> RDS >> Mysql

Какви са настройките на драйвера на JDBC-mysql за нормално боравене с DATETIME и TIMESTAMP в UTC?

Решението е да зададете параметър за 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 грешно маркиран към часовата зона по подразбиране на JVM, дори когато tz параметърът е настроен на нещо друго:

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 като String, представляващ това, което часовникът ще показва в часовата зона по подразбиране на JVM, вместо низово представяне на часа в UTC. В 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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MYSQL, много бавно подреждане по

  2. Как да актуализирате база данни на mysql без презареждане на страницата

  3. Как да проверя дали съществува индекс в поле на таблица в MySQL?

  4. SQLAlchemy Reflection:Как да направя заявка за данни от конкретни колони?

  5. Различни начини за попълване на потребителите на MySQL