Jordan, sebenarnya Anda punya ide yang tepat. Masalahnya adalah ada bug di driver MySQL JDBC dan argumen Kalender sepenuhnya diabaikan secara default. Lihat kode sumber untuk PreparedStatement untuk benar-benar melihat apa yang terjadi.
Perhatikan itu memformat Timestamp menggunakan zona waktu JVM. Ini hanya akan berfungsi jika JVM Anda menggunakan zona waktu UTC. Objek Kalender sepenuhnya diabaikan.
this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss''", Locale.US);
timestampString = this.tsdf.format(x);
Agar MySQL dapat menggunakan argumen Kalender, Anda harus menonaktifkan kode tanggal/waktu lama dengan opsi koneksi berikut:
useLegacyDatetimeCode=false
Jadi Anda mungkin menggunakannya saat menghubungkan ke database seperti ini:
String url = "jdbc:mysql://localhost/tz?useLegacyDatetimeCode=false"
Jika Anda menonaktifkan kode tanggal waktu lama menggunakan baris di atas, maka itu AKAN membuat Stempel Waktu Anda di zona waktu Kalender target:
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);
}
Cukup mudah untuk melihat apa yang terjadi di sini. Jika Anda memasukkan objek Kalender, itu akan menggunakan ini saat memformat data. Jika tidak, itu akan menggunakan zona waktu database untuk memformat data. Anehnya, jika Anda memasukkan Kalender, itu juga akan mengatur waktu ke nilai Timestamp yang diberikan (yang tampaknya tidak ada gunanya).