Conversione del fuso orario

Ho bisogno di convertire da un fuso orario in un altro fuso orario nel mio progetto.

Sono in grado di convertire dal fuso orario corrente a un altro, ma non da un fuso orario diverso a un altro.

Ad esempio, sono in India e sono in grado di convertire dall’India agli Stati Uniti utilizzando Date d=new Date(); e assegnandolo a un object del calendario e impostando il fuso orario.

Tuttavia, non posso farlo da fuso orario diverso a un altro fuso orario. Ad esempio, sono in India, ma ho difficoltà a convertire i fusi orari dagli Stati Uniti al Regno Unito.

tl; dr

 ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" ) // Current moment in a particular time zone. .withZoneSameInstant( ZoneId.of( "Asia/Kolkata" ) // Same moment adjusted into another time zone. 

Dettagli

La class java.util.Date non ha un fuso orario assegnato , tuttavia l’implementazione toString applica in modo confuso il fuso orario predefinito corrente della JVM.

Evita java.util.Date e .Calendar

Questo è uno dei molti motivi per evitare le notoriamente fastidiose classi java.util.Date, .Calendar e SimpleDateFormat in bundle con Java. Evitalo. Usa invece:

  • Il pacchetto java.time integrato in Java 8 e ispirato a Joda-Time.
  • Joda-Time

java.time

Java 8 e versioni successive ha il pacchetto java.time integrato. Questo pacchetto è stato ispirato da Joda-Time . Mentre condividono alcune somiglianze e nomi di class, sono diversi; ognuno ha caratteristiche le altre mancanze. Una differenza notevole è che java.time evita i costruttori, invece utilizza metodi di istanziazione statici. Entrambe le strutture sono guidate dallo stesso uomo, Stephen Colbourne .

Gran parte della funzionalità java.time è stata sottoposta a backup su Java 6 e 7 nel progetto ThreeTen-Backport . Ulteriormente adattato ad Android nel progetto ThreeTenABP .

Nel caso di questa domanda, funzionano allo stesso modo. Specificare un fuso orario e chiamare un metodo now per ottenere il momento corrente, quindi creare una nuova istanza basata sulla vecchia istanza immutabile per regolare il fuso orario.

Nota le due diverse classi di fuso orario. Uno è un fuso orario con nome che include tutte le regole per l’ora legale e altre anomalie di questo tipo più uno scostamento da UTC mentre l’altro è solo l’offset.

 ZoneId zoneMontréal = ZoneId.of("America/Montreal"); ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal ); ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo ); ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC ); 

Joda-Time

Segue un codice di esempio in Joda-Time 2.3. Cerca StackOveflow per molti altri esempi e molte discussioni.

 DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" ); DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" ); DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" ); DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone. DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata ); DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork ); DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC ); // Built-in constant for UTC. 

Abbiamo quattro rappresentazioni dello stesso momento nella timeline dell’Universo.


In realtà la class java.util.Date ha un fuso orario nascosto nel suo codice sorgente . Ma la class ignora quel fuso orario per la maggior parte degli scopi pratici. Quindi, come abbreviazione, si dice spesso che juDate non ha un fuso orario assegnato. Confondere? Sì. Evita il casino che è juDate e vai con Joda-Time e / o java.time.

Qualche esempio

Converti tempo tra fuso orario

Conversione di tempi tra fusi orari

 import java.util.Calendar; import java.util.GregorianCalendar; import java.util.TimeZone; public class TimeZoneExample { public static void main(String[] args) { // Create a calendar object and set it time based on the local // time zone Calendar localTime = Calendar.getInstance(); localTime.set(Calendar.HOUR, 17); localTime.set(Calendar.MINUTE, 15); localTime.set(Calendar.SECOND, 20); int hour = localTime.get(Calendar.HOUR); int minute = localTime.get(Calendar.MINUTE); int second = localTime.get(Calendar.SECOND); // Print the local time System.out.printf("Local time : %02d:%02d:%02d\n", hour, minute, second); // Create a calendar object for representing a Germany time zone. Then we // wet the time of the calendar with the value of the local time Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin")); germanyTime.setTimeInMillis(localTime.getTimeInMillis()); hour = germanyTime.get(Calendar.HOUR); minute = germanyTime.get(Calendar.MINUTE); second = germanyTime.get(Calendar.SECOND); // Print the local time in Germany time zone System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second); } } 
  Date date = new Date(); String formatPattern = ....; SimpleDateFormat sdf = new SimpleDateFormat(formatPattern); TimeZone T1; TimeZone T2; // set the Calendar of sdf to timezone T1 sdf.setTimeZone(T1); System.out.println(sdf.format(date)); // set the Calendar of sdf to timezone T2 sdf.setTimeZone(T2); System.out.println(sdf.format(date)); // Use the 'calOfT2' instance-methods to get specific info // about the time-of-day for date 'date' in timezone T2. Calendar calOfT2 = sdf.getCalendar(); 

Il fuso orario “predefinito” può essere evitato completamente semplicemente impostando il fuso orario in modo appropriato per l’object Calendar . Tuttavia, suggerirei personalmente di utilizzare Joda Time come API di livello superiore per le operazioni di data e ora in Java. Tra l’altro, la conversione del fuso orario è molto semplice in Joda.

Non è chiaro quale sia il tuo codice attuale e perché puoi convertire solo tramite il fuso orario predefinito, ma in Joda Time devi semplicemente specificare il fuso orario in modo esplicito quando crei (diciamo) un object DateTime , e quindi usi withZone(DateTimeZone zone) .

Se potessi dirci di più su come stai ricevendo i dati di input, potremmo dare un esempio più completo.

Puoi utilizzare il seguente snippet di codice

 String dateString = "14 Jul 2014 00:11:04 CEST"; date = formatter.parse(dateString); System.out.println(formatter.format(date)); // Set the formatter to use a different timezone - Indochina Time formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok")); System.out.println("ICT time : "+formatter.format(date)); 

Se non vuoi usare Joda, ecco un modo deterministico usando le librerie incorporate.

Prima di tutto ti consiglio di forzare la tua JVM di default in un fuso orario. Questo risolve i problemi che potresti incontrare quando sposti la tua JVM da una macchina all’altra che sono impostate su fusi orari diversi, ma i tuoi dati sorgente sono sempre un determinato fuso orario. Ad esempio, diciamo che i tuoi dati sono sempre PDT / PST fuso orario, ma si esegue su una casella che è impostata su fuso orario UTC.

Il seguente frammento di codice imposta il fuso orario predefinito nella mia JVM:

  //You can either pass the JVM a parameter that //enforces a TZ: java -Duser.timezone=UTC or you can do it //programatically like this TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); TimeZone.setDefault(tz); 

Ora diciamo che la data sorgente è in arrivo come PDT / PST ma è necessario convertirla in UTC. Questi sono i passaggi:

  DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC")); String dateStrInPDT = "2016-05-19 10:00:00"; Date dateInPDT = dateFormat.parse(dateStrInPDT); String dateInUtc = dateFormatUtc.format(dateInPDT); System.out.println("Date In UTC is " + dateInUtc); 

L’output sarebbe:

 Date In UTC is 2016-05-19 17:00:00 

puoi fare così per ottenere l’ora corrente in un altro fuso orario

 Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan")); japanCal.setTimeInMillis(local.getTimeInMillis()); 

Dipende da cosa intendi per “conversione”.

Potrebbe essere semplice come impostare il fuso orario nel FORMATTO e non masticare affatto con il Calendario.

 Calendar cal = Calendar.getInstance(); TimeZone tzUTC = TimeZone.getTimeZone( "UTC" ); TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" ); DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm az" ); dtfmt.setTimeZone( tzUTC ); System.out.println( "UTC: " + dtfmt.format( cal.getTime() )); dtfmt.setTimeZone( tzPST ); System.out.println( "PST: " + dtfmt.format( cal.getTime() )); 

Questa non è la risposta, ma potrebbe aiutare qualcuno a cercare di generare date con lo stesso fuso orario e applicare un altro offset di fuso orario. È utile quando il tuo server delle applicazioni è in esecuzione in un fuso orario e il tuo database in un altro.

 public static Date toGreekTimezone (Date date) { ZoneId greek = ZoneId.of(EUROPE_ATHENS); ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek); ZoneId def = ZoneId.systemDefault(); ZonedDateTime defDate = greekDate.withZoneSameLocal(def); return Date.from(defDate.toInstant()); } 

È ansible utilizzare il java.time.ZoneDateTime#ofInstant() :

 import java.time.*; public class TimeZonesConversion { static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) { return ZonedDateTime.ofInstant( time.toInstant(), newTimeZone); }; public static void main(String... args) { ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07")); ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone()); System.out.println("MST(" + mstTime + ") = " + localTime); } } 
 public static void convertTimeZone(Date date, TimeZone fromTimeZone, TimeZone toTimeZone) { long milliseconds = date.getTime(); milliseconds += (fromTimeZone.getRawOffset() * -1); if (fromTimeZone.inDaylightTime(date)) { milliseconds += (fromTimeZone.getDSTSavings() * -1); } milliseconds += toTimeZone.getRawOffset(); if (toTimeZone.inDaylightTime(date)) { milliseconds += toTimeZone.getDSTSavings(); } date.setTime(milliseconds); }