Jordan, in realtà hai avuto l'idea giusta. Il problema è che c'è un bug nel driver MySQL JDBC e l'argomento Calendar è completamente ignorato per impostazione predefinita. Guarda il codice sorgente di PreparedStatement per vedere davvero cosa sta succedendo.
Si noti che il formato è il Timestamp che utilizza il fuso orario della JVM. Funzionerà solo se la tua JVM utilizza il fuso orario UTC. L'oggetto Calendario viene completamente ignorato.
this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss''", Locale.US);
timestampString = this.tsdf.format(x);
Affinché MySQL utilizzi l'argomento Calendar, devi disabilitare il codice data/ora legacy con la seguente opzione di connessione:
useLegacyDatetimeCode=false
Quindi potresti usarlo quando ti connetti al database in questo modo:
String url = "jdbc:mysql://localhost/tz?useLegacyDatetimeCode=false"
Se disabiliti il codice datetime legacy utilizzando la riga sopra, il timestamp verrà visualizzato nel fuso orario del calendario di destinazione:
if (targetCalendar != null) {
targetCalendar.setTime(x);
this.tsdf.setTimeZone(targetCalendar.getTimeZone());
timestampString = this.tsdf.format(x);
} else {
this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ());
timestampString = this.tsdf.format(x);
}
È abbastanza facile vedere cosa sta succedendo qui. Se passi un oggetto Calendar, lo utilizzerà durante la formattazione dei dati. In caso contrario, utilizzerà il fuso orario del database per formattare i dati. Stranamente, se passi un Calendario, imposterà anche l'ora sul valore di Timestamp (che sembra essere inutile).