zoneid Java.sql.Timestamp è specifico per il fuso orario?




zoneid europe rome (4)

È specifico del tuo autista. È necessario fornire un parametro nel programma Java per indicare il fuso orario che si desidera utilizzare.

java -Duser.timezone="America/New_York" GetCurrentDateTimeZone

Inoltre questo:

to_char(new_time(sched_start_time, 'CURRENT_TIMEZONE', 'NEW_TIMEZONE'), 'MM/DD/YY HH:MI AM')

Può anche essere utile nel gestire correttamente la conversione. Preso da here

Devo memorizzare UTC dateTime in DB.
Ho convertito la data indicata in fuso orario specifico in UTC. per quello ho seguito il codice qui sotto.
La mia data di inputTime è "20121225 10:00:00 Z" Il fuso orario è "Asia / Calcutta"
My Server / DB (oracle) è in esecuzione nello stesso fuso orario (IST) "Asia / Calcutta"

Ottieni l'oggetto Date in questo specifico fuso orario

        String date = "20121225 10:00:00 Z";
        String timeZoneId = "Asia/Calcutta";
        TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);

        DateFormat dateFormatLocal = new SimpleDateFormat("yyyyMMdd HH:mm:ss z");
                    //This date object is given time and given timezone
        java.util.Date parsedDate = dateFormatLocal.parse(date + " "  
                         + timeZone.getDisplayName(false, TimeZone.SHORT));

        if (timeZone.inDaylightTime(parsedDate)) {
            // We need to re-parse because we don't know if the date
            // is DST until it is parsed...
            parsedDate = dateFormatLocal.parse(date + " "
                    + timeZone.getDisplayName(true, TimeZone.SHORT));
        }

       //assigning to the java.sql.TimeStamp instace variable
        obj.setTsSchedStartTime(new java.sql.Timestamp(parsedDate.getTime()));

Archivia in DB

        if (tsSchedStartTime != null) {
            stmt.setTimestamp(11, tsSchedStartTime);
        } else {
            stmt.setNull(11, java.sql.Types.DATE);
        }

PRODUZIONE

DB (oracle) ha memorizzato la stessa dateTime: "20121225 10:00:00 non in UTC.

Ho confermato dal sottostante sql.

     select to_char(sched_start_time, 'yyyy/mm/dd hh24:mi:ss') from myTable

Anche il mio server DB è in esecuzione sullo stesso fuso orario "Asia / Calcutta"

Mi dà le seguenti apparenze

  1. Date.getTime() non è in UTC
  2. O il Timestamp ha un impatto sul fuso orario durante l'archiviazione in DB. Cosa sto facendo male qui?

Un'altra domanda:

timeStamp.toString() stampa nel fuso orario locale come fa java.util.date ? Non UTC?


Penso che la risposta corretta dovrebbe essere java.sql.Timestamp NON è specifico per il fuso orario. Timestamp è un composto di java.util.Date e un valore separato di nanosecondi. Non ci sono informazioni sul fuso orario in questa classe. Così come Date questa classe detiene semplicemente il numero di millisecondi dal 1 gennaio 1970, 00:00:00 GMT + nanos.

In PreparedStatement.setTimestamp (int parameterIndex, Timestamp x, Calendar cal) Calendar viene utilizzato dal driver per modificare il fuso orario predefinito. Ma Timestamp detiene ancora millisecondi nel GMT.

API non è chiara su come si debba utilizzare esattamente il driver JDBC per Calendar. I provider sembrano sentirsi liberi su come interpretarlo, ad esempio l'ultima volta che ho lavorato con MySQL 5.5 Calendar il driver ha semplicemente ignorato Calendar sia in PreparedStatement.setTimestamp che in ResultSet.getTimestamp.


Sebbene non sia specificato esplicitamente per setTimestamp(int parameterIndex, Timestamp x) driver devono seguire le regole stabilite da setTimestamp(int parameterIndex, Timestamp x, Calendar cal) javadoc :

Imposta il parametro designato sul valore java.sql.Timestamp specificato, utilizzando l'oggetto Calendar specificato. Il driver utilizza l'oggetto Calendar per costruire un valore TIMESTAMP SQL, che il driver quindi invia al database. Con un oggetto Calendar , il driver può calcolare il timestamp tenendo conto di un fuso orario personalizzato. Se non viene specificato alcun oggetto Calendar , il driver utilizza il fuso orario predefinito, che è quello della macchina virtuale che esegue l'applicazione.

Quando si chiama con setTimestamp(int parameterIndex, Timestamp x) il driver JDBC utilizza il fuso orario della macchina virtuale per calcolare la data e l'ora del timestamp in quel fuso orario. Questa data e ora è ciò che è memorizzato nel database, e se la colonna del database non memorizza le informazioni sul fuso orario, allora qualsiasi informazione sulla zona viene persa (il che significa che dipende dalle applicazioni che usano il database per usare il stesso fuso orario in modo coerente o trovare un altro schema per discernere il fuso orario (ovvero memorizzare in una colonna separata).

Ad esempio: il fuso orario locale è GMT + 2. Si memorizza "2012-12-25 10:00:00 UTC". Il valore effettivo memorizzato nel database è "2012-12-25 12:00:00". Lo recuperi di nuovo: lo recuperi di nuovo come "2012-12-25 10:00:00 UTC" (ma solo se lo recuperi utilizzando getTimestamp(..) ), ma quando un'altra applicazione accede al database in fuso orario GMT +0, recupererà il timestamp come "2012-12-25 12:00:00 UTC".

Se si desidera archiviarlo in un fuso orario diverso, è necessario utilizzare il setTimestamp(int parameterIndex, Timestamp x, Calendar cal) con un'istanza di Calendar nel fuso orario richiesto. Assicurati di utilizzare anche il getter equivalente con lo stesso fuso orario durante il recupero dei valori (se utilizzi un TIMESTAMP senza informazioni sul fuso orario nel database).

Quindi, supponendo che tu voglia memorizzare il fuso orario GMT attuale, devi usare:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
stmt.setTimestamp(11, tsSchedStartTime, cal);

Con JDBC 4.2 un driver compatibile dovrebbe supportare java.time.LocalDateTime (e java.time.LocalTime ) per TIMESTAMP (e TIME ) tramite get/set/updateObject . Le classi java.time.Local* sono prive di fuso orario, quindi non è necessario applicare alcuna conversione (anche se ciò potrebbe aprire una nuova serie di problemi se il codice ha assunto un fuso orario specifico).


Per Mysql abbiamo una limitazione. Nel driver Mysql doc , abbiamo:

Di seguito sono riportati alcuni problemi e limitazioni noti per MySQL Connector / J: Quando Connector / J recupera i timestamp per un giorno di commutazione dell'ora legale (DST) utilizzando il metodo getTimeStamp () sul set di risultati, alcuni dei valori restituiti potrebbero essere errati. Gli errori possono essere evitati utilizzando le seguenti opzioni di connessione durante la connessione a un database:

useTimezone=true
useLegacyDatetimeCode=false
serverTimezone=UTC

Quindi, quando non usiamo questi parametri e chiamiamo setTimestamp or getTimestamp con calendario o senza calendario, abbiamo il timestamp nel fuso orario di jvm.

Esempio :

Il fuso orario di jvm è GMT + 2. Nel database, abbiamo un timestamp: 1461100256 = 19/04/16 21: 10: 56,000000000 GMT

Properties props = new Properties();
props.setProperty("user", "root");
props.setProperty("password", "");
props.setProperty("useTimezone", "true");
props.setProperty("useLegacyDatetimeCode", "false");
props.setProperty("serverTimezone", "UTC");
Connection con = DriverManager.getConnection(conString, props);
......
Calendar nowGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Calendar nowGMTPlus4 = Calendar.getInstance(TimeZone.getTimeZone("GMT+4"));
......
rs.getTimestamp("timestampColumn");//Oracle driver convert date to jvm timezone and Mysql convert date to GMT (specified in the parameter)
rs.getTimestamp("timestampColumn", nowGMT);//convert date to GMT 
rs.getTimestamp("timestampColumn", nowGMTPlus4);//convert date to GMT+4 timezone

Il primo metodo restituisce: 1461100256000 = 19/04/2016 - 21:10:56 GMT

Il secondo metodo restituisce: 1461100256000 = 19/04/2016 - 21:10:56 GMT

Il terzo metodo restituisce: 1461085856000 = 19/04/2016 - 17:10:56 GMT

Invece di Oracle, quando usiamo le stesse chiamate, abbiamo:

Il primo metodo restituisce: 1461093056000 = 19/04/2016 - 19:10:56 GMT

Il secondo metodo restituisce: 1461100256000 = 19/04/2016 - 21:10:56 GMT

Il terzo metodo restituisce: 1461085856000 = 19/04/2016 - 17:10:56 GMT

NB: non è necessario specificare i parametri per Oracle.





jdbc