Convertir date / heure pour un fuseau horaire donné – Java

Je veux convertir cet horodatage GMT en GMT + 13:

2011-10-06 03:35:05 

J’ai essayé environ 100 combinaisons différentes de DateFormat, TimeZone, Date, GregorianCalendar, etc. pour essayer de faire cette tâche TRES basique.

Ce code fait ce que je veux pour le temps actuel:

 Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z"); formatter.setTimeZone(TimeZone.getTimeZone("GMT+13")); Ssortingng newZealandTime = formatter.format(calendar.getTime()); 

Mais ce que je veux, c’est régler l’heure plutôt que d’utiliser l’heure actuelle.

J’ai trouvé que chaque fois que j’essaie de régler l’heure comme ceci:

 calendar.setTime(new Date(1317816735000L)); 

la TimeZone de la machine locale est utilisée. Pourquoi donc? Je sais que lorsque “new Date ()” renvoie l’heure UTC + 0 alors pourquoi lorsque vous définissez le temps en millisecondes, ne suppose-t-il plus que l’heure est en UTC?

Est possible de:

  1. Définir l’heure sur un object (Calendrier / Date / TimeStamp)
  2. (Éventuellement) Définir la TimeZone de l’horodatage initial (calendar.setTimeZone (…))
  3. Formatez l’horodatage avec une nouvelle TimeZone (formatter.setTimeZone (…)))
  4. Renvoie une chaîne avec l’heure du nouveau fuseau horaire. (formatter.format (calendar.getTime ()))

Merci d’avance pour toute aide: D

Comprendre le fonctionnement du temps d’informatique est très important. Cela étant dit, je suis d’accord que si une API est créée pour vous aider à traiter le temps d’ordinateur comme le temps réel, elle devrait fonctionner de manière à pouvoir la traiter en temps réel. C’est en grande partie le cas, mais il y a des oublis majeurs qui nécessitent une attention particulière.

En tout cas je m’égare !! Si vous avez votre décalage UTC (il est préférable de travailler en UTC que les décalages GMT), vous pouvez calculer le temps en millisecondes et l’append à votre horodatage. Notez qu’un horodatage SQL peut varier d’un horodatage Java, car la manière dont le délai est calculé n’est pas toujours la même – en fonction des technologies de firebase database et des systèmes d’exploitation.

Je vous conseille d’utiliser System.currentTimeMillis () comme vos horodatages, car ceux-ci peuvent être traités de manière plus cohérente dans Java sans se soucier de la conversion des horodatages SQL en objects Date Java, etc.

Pour calculer votre décalage, vous pouvez essayer quelque chose comme ceci:

 Long gmtTime =1317951113613L; // 2.32pm NZDT Long timezoneAlteredTime = 0L; if (offset != 0L) { int multiplier = (offset*60)*(60*1000); timezoneAlteredTime = gmtTime + multiplier; } else { timezoneAlteredTime = gmtTime; } Calendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(timezoneAlteredTime); DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z"); formatter.setCalendar(calendar); formatter.setTimeZone(TimeZone.getTimeZone(timeZone)); Ssortingng newZealandTime = formatter.format(calendar.getTime()); 

J’espère que ceci est utile!

Pour moi, le moyen le plus simple est de:

 Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //Here you say to java the initial timezone. This is the secret sdf.setTimeZone(TimeZone.getTimeZone("UTC")); //Will print in UTC System.out.println(sdf.format(calendar.getTime())); //Here you set to your timezone sdf.setTimeZone(TimeZone.getDefault()); //Will print on your default Timezone System.out.println(sdf.format(calendar.getTime())); 

Comme toujours, je vous recommande de lire cet article sur la date et l’heure en Java afin de le comprendre.

L’idée de base est que «sous le capot» tout se fait en millisecondes UTC depuis l’époque. Cela signifie que c’est plus facile si vous travaillez sans utiliser de fuseau horaire, à l’exception du formatage Ssortingng pour l’utilisateur.

Par conséquent, je sauterais la plupart des étapes que vous avez suggérées.

  1. Définissez l’heure sur un object (Date, Calendrier, etc.).
  2. Définissez le fuseau horaire sur un object formateur.
  3. Renvoie une chaîne à partir du formateur.

Alternativement, vous pouvez utiliser le temps Joda . J’ai entendu dire qu’il s’agissait d’une API datetime beaucoup plus intuitive.

tl; dr

Si donné entrée de 1317816735000L

 Instant.ofEpochMilli( 1_317_816_735_000L ) // Represent a moment in UTC using a count of milliseconds since the epoch reference of 1970-01-01T00:00Z. .atZone( ZoneId.of( "Pacific/Auckland" ) ) // Adjust from UTC into the wall-clock time used by the people of a certain region (a time zone). Returns a `ZonedDateTime` object. .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ) .withLocale( new Locale( "en" , "NZ" ) ) // Locale specifies the human language and cultural norms used in localization. ) // Returns a `Ssortingng` object that represents the value of our `ZonedDateTime` object's value. 

Si donné entrée de 2011-10-06 03:35:05 : 2011-10-06 03:35:05 : 2011-10-06 03:35:05

 LocalDateTime.parse( // Parse input ssortingng lacking any indicator of time zone or offset-from-UTC using the `LocalDateTime` class. "2011-10-06 03:35:05" .replace( " " , "T" ) // Comply with ISO 8601 standard by replacing SPACE in the middle with a `T`. ) // Returns a `LocalDateTime` object. .atZone( // Adjust from UTC into the wall-clock time used by the people of a certain region (a time zone). Returns a `ZonedDateTime` object. ZoneId.of( "Pacific/Auckland" ) // Always specify a time zone by `Continent/Region` name. Never use 3-4 pseudo-time-zones such as `PST`, `CST`, or `IST`. ) // Returns a `ZonedDateTime` object. 

java.time

La question et la plupart des réponses utilisent des classes date-heure héritées obsolètes des premières versions de Java. Ces anciennes classes se sont avérées gênantes et déroutantes. Évite-les. Utilisez plutôt les classes java.time.

ISO 8601

Votre chaîne de saisie est presque au format standard ISO 8601 . Il suffit de remplacer l’espace au milieu par un T

 Ssortingng input = "2011-10-06 03:35:05".replace( " " , "T" ) ; // Comply with ISO 8601 standard format by replacing the SPACE with a `T`. 

Les classes java.time utilisent ces formats standard par défaut lors de l’parsing / génération de chaînes. Donc, pas besoin de spécifier un modèle de formatage.

LocalDateTime

Maintenant, LocalDateTime tant que LocalDateTime car l’entrée ne LocalDateTime aucune information sur l’offset-from-UTC ou le fuseau horaire. Un LocalDateTime n’a pas de concept de décalage ni de fuseau horaire, donc il ne représente pas un moment réel sur la ligne de temps.

 LocalDateTime ldt = LocalDateTime.parse( input ); 

ZoneOffset

Vous semblez dire que dans le contexte commercial, vous savez que l’intention de cette chaîne est de représenter un moment en avance de 13 heures sur l’UTC. Nous instancions donc un ZoneOffset .

 ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe. 

OffsetDateTime

Appliquez-le pour obtenir un object OffsetDateTime . Cela devient un moment réel sur la chronologie.

 OffsetDateTime odt = ldt.atOffset( offset); 

ZoneId

Mais alors vous mentionnez la Nouvelle-Zélande. Donc, vous aviez un fuseau horaire spécifique en tête. Un fuseau horaire est un décalage par rapport à l’heure UTC plus un ensemble de règles pour gérer les anomalies telles que l’heure d’été. Nous pouvons donc spécifier un ZoneId à un ZonedDateTime plutôt qu’un simple décalage.

Spécifiez un nom de fuseau horaire approprié . N’utilisez jamais l’abréviation de 3-4 lettres comme EST ou IST car ce ne sont pas de véritables fuseaux horaires, non standardisés, et même pas uniques (!). Par exemple, Pacific/Auckland .

 ZoneId z = ZoneId.of( "Pacific/Auckland" ); 

ZonedDateTime

Appliquez le ZoneId .

 ZonedDateTime zdt = ldt.atZone( z ); 

Vous pouvez facilement ajuster dans une autre zone pour le même moment sur la ligne de temps.

 ZoneId zParis = ZoneId.of( "Europe/Paris" ); ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time. 

Comptez de l’époque

Je déconseille fortement de gérer les valeurs date-heure en tant que décompte d’époque, par exemple en millisecondes depuis le début de 1970 UTC. Mais si vous devez, créez un Instant partir d’un tel nombre.

 Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L ); 

Puis, si vous le souhaitez, atsortingbuez un fuseau horaire comme indiqué ci-dessus pour vous éloigner de l’UTC.

 ZoneId z = ZoneId.of( "Pacific/Auckland" ); ZonedDateTime zdt = instant.atZone( z ); 

Votre valeur de 1_317_816_735_000L est:

  • 2011-10-05T12:12:15Z (mer. 05 oct. 2011 12:12:15 GMT)
  • 2011-10-06T01:12:15+13:00[Pacific/Auckland] (jeudi 06 octobre 2011 01:12:15 à Auckland en Nouvelle-Zélande).

Générer des chaînes

Pour générer une chaîne au format ISO 8601 standard, il suffit d’appeler toSsortingng . Notez que ZonedDateTime étend judicieusement le format standard en ajoutant le nom du fuseau horaire entre crochets.

 Ssortingng output = zdt.toSsortingng(); 

Pour les autres formats, recherchez Stack Overflow pour la classe DateTimeFormatter . Déjà couvert plusieurs fois.

Spécifiez un FormatStyle et un FormatStyle .

 Locale l = new Locale( "en" , "NZ" ); DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l ); Ssortingng output = zdt.format( f ); 

À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciennes classes de date / heure héritées telles que java.util.Date , Calendar et SimpleDateFormat .

Le projet Joda-Time , maintenant en mode maintenance , conseille la migration vers les classes java.time .

Pour en savoir plus, consultez le didacticiel Oracle . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Vous pouvez échanger des objects java.time directement avec votre firebase database. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de classes java.sql.* .

Où obtenir les classes java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 et versions ultérieures
    • Intégré
    • Partie de l’API Java standard avec une implémentation intégrée.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité java.time est transférée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android
    • Versions ultérieures des implémentations de bundles Android des classes java.time.
    • Pour Android antérieur (<26), le projet ThreeTenABP adapte ThreeTen-Backport (mentionné ci-dessus). Voir Comment utiliser ThreeTenABP… .

Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts futurs à java.time. Vous pouvez y trouver des classes utiles telles que Interval , YearWeek , YearQuarter , etc.

J’ai jeté un coup d’oeil et je ne pense pas qu’il y ait un fuseau horaire en Java qui soit GMT + 13. Donc, je pense que vous devez utiliser:

 Calendar calendar = Calendar.getInstance(); //OR Calendar.getInstance(TimeZone.getTimeZone("GMT")); calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13); Date d = calendar.getTime(); 

(S’il y a alors changer “GMT” à ce fuseau horaire et supprimer la deuxième ligne de code)

OU

 SimpleDateFormat df = new SimpleDateFormat(); df.setTimeZone(TimeZone.getTimeZone("GMT+13")); System.out.println(df.format(c.getTime())); 

Si vous souhaitez définir une heure / date spécifique, vous pouvez également utiliser:

  calendar.set(Calendar.DATE, 15); calendar.set(Calendar.MONTH, 3); calendar.set(Calendar.YEAR, 2011); calendar.set(Calendar.HOUR_OF_DAY, 13); calendar.set(Calendar.MINUTE, 45); calendar.set(Calendar.SECOND, 00); 

La solution est en réalité assez simple (Java pur et simple):

 System.out.println(" NZ Local Time: 2011-10-06 03:35:05"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter); ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00")); LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); System.out.println("UTC Local Time: "+localUTC.format(formatter)); 

SORTIE EST:

  NZ Local Time: 2011-10-06 03:35:05 UTC Local Time: 2011-10-05 14:35:05 

Joda-Time

Les classes java.util.Date/Calendar sont un gâchis et doivent être évitées.

Mise à jour: le projet Joda-Time est en mode maintenance. L’équipe conseille la migration vers les classes java.time.

Voici votre réponse en utilisant la bibliothèque Joda-Time 2.3. Très facile.

Comme indiqué dans l’exemple de code, je vous suggère d’utiliser autant que possible des fuseaux horaires nommés pour que votre programmation puisse gérer l’ heure d’été et d’autres anomalies.

Si vous avez placé un T au milieu de votre chaîne au lieu d’un espace, vous pouvez ignorer les deux premières lignes de code, en traitant un formateur pour parsingr la chaîne. Le constructeur DateTime peut prendre une chaîne au format ISO 8601 .

 // © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so. // import org.joda.time.*; // import org.joda.time.format.*; // Parse ssortingng as a date-time in UTC (no time zone offset). DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" ); DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" ); // Adjust for 13 hour offset from UTC/GMT. DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 ); DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen ); // Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies. // Time Zone list… http://joda-time.sourceforge.net/timezones.html DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" ); DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu ); 

Vider ces valeurs…

 System.out.println( "dateTimeInUTC: " + dateTimeInUTC ); System.out.println( "thirteenDateTime: " + thirteenDateTime ); System.out.println( "tongatapuDateTime: " + tongatapuDateTime ); 

Quand courir…

 dateTimeInUTC: 2011-10-06T03:35:05.000Z thirteenDateTime: 2011-10-06T16:35:05.000+13:00 tongatapuDateTime: 2011-10-06T16:35:05.000+13:00 

J’ai essayé ce code

 try{ SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z"); Date datetime = new Date(); System.out.println("date "+sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); System.out.println("GMT "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("GMT+13")); System.out.println("GMT+13 "+ sdf.format(datetime)); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println("utc "+sdf.format(datetime)); Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z"); formatter.setTimeZone(TimeZone.getTimeZone("GMT+13")); Ssortingng newZealandTime = formatter.format(calendar.getTime()); System.out.println("using calendar "+newZealandTime); }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } 

et obtenir ce résultat

 date 06-10-2011 10:40:05 +0530 GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05 GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05 utc 06-10-2011 05:10:05 +0000 using calendar 06 Oct 2011 18:10:05 GMT+13:00 

Nous pouvons gérer cela en utilisant la valeur de décalage

  public static long convertDateTimeZone(long lngDate, Ssortingng fromTimeZone, Ssortingng toTimeZone){ TimeZone toTZ = TimeZone.getTimeZone(toTimeZone); Calendar toCal = Calendar.getInstance(toTZ); TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone); Calendar fromCal = Calendar.getInstance(fromTZ); fromCal.setTimeInMillis(lngDate); toCal.setTimeInMillis(fromCal.getTimeInMillis() + toTZ.getOffset(fromCal.getTimeInMillis()) - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis())); return toCal.getTimeInMillis(); } 

Extrait de code de test:

  System.out.println(new Date().getTime()) System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone .getDefault().getID(), "EST")); 

Sortie: 1387353270742 1387335270742

Nous pouvons obtenir l’horodatage UTC / GMT à partir de la date donnée.

 /** * Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss) */ public static long getGMTTimeStampFromDate(Ssortingng datetime) { long timeStamp = 0; Date localTime = new Date(); Ssortingng format = "dd-MM-yyyy HH:mm:ss"; SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format); sdfLocalFormat.setTimeZone(TimeZone.getDefault()); try { localTime = (Date) sdfLocalFormat.parse(datetime); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.getDefault()); TimeZone tz = cal.getTimeZone(); cal.setTime(localTime); timeStamp = (localTime.getTime()/1000); Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime + ", GMT TimeStamp : " + localTime.getTime()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return timeStamp; } 

Il renverra l’heure UTC en fonction de la date de passage.

  • Nous pouvons faire l’inverse comme horodatage UTC à la date et à l’heure actuelles (vice versa)

      public static Ssortingng getLocalTimeFromGMT(long gmtTimeStamp) { try{ Calendar calendar = Calendar.getInstance(); TimeZone tz = TimeZone.getDefault(); calendar.setTimeInMillis(gmtTimeStamp * 1000); // calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis())); SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); Date currenTimeZone = (Date) calendar.getTime(); return sdf.format(currenTimeZone); }catch (Exception e) { } return ""; } 

J’espère que cela aidera les autres. Merci!!

Un moyen rapide est:

 Ssortingng dateText ="Thu, 02 Jul 2015 21:51:46"; long hours = -5; // time difference between places DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH); LocalDateTime date = LocalDateTime.parse(dateText, formatter); date = date.with(date.plusHours(hours)); System.out.println("NEW DATE: "+date); 

Sortie

NOUVELLE DATE: 2015-07-02T16: 51: 46

 public Timestamp convertLocalTimeToServerDatetime(Ssortingng dt,Ssortingng timezone){ Ssortingng clientDnT = dt ;// "2017-06-01 07:20:00"; try{ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(clientDnT); TimeZone tz = TimeZone.getTimeZone(timezone.sortingm()); // get time zone of user sdf.setTimeZone(tz); // Convert to servertime zone SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); TimeZone tzInAmerica = TimeZone.getDefault(); sdf1.setTimeZone(tzInAmerica); // assign date to date Ssortingng serverDate = sdf1.format(date); // Convert to servertime zone to Timestamp Date date2 = sdf.parse(serverDate); Timestamp tsm = new Timestamp(date2.getTime()); return tsm; } catch(Exception e){ System.err.println(e); } return null; } 

Un moyen facile Une chose importante à retenir est que Date ne conserve pas le fuseau horaire, son seul nombre de long millis , comme il a été traité ici.

 /** * Converts source in GMT+0 to timezone specified by server * * @throws IllegalStateException if server timezone wasnt set */ public static Date convertGmt(Date source) { if (timeZoneServer == null) { throw new IllegalStateException("Server timezone wasnt set"); } long rawOffset = timeZoneServer.getRawOffset(); Date dest = new Date(source.getTime() + rawOffset); return dest; } /** * Converts source in device timezone format to GMT */ public static Date convertToGmt(Date source) { int rawOffset = TimeZone.getDefault().getRawOffset(); Date dest = new Date(source.getTime() - rawOffset); return dest; } 

TimezoneServer est quelque chose comme TimeZone timeZoneServer = TimeZone.getTimeZone("GMT+1")

Votre approche fonctionne sans aucune modification.

 Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); // Timestamp for 2011-10-06 03:35:05 GMT calendar.setTime(new Date(1317872105000L)); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); formatter.setTimeZone(TimeZone.getTimeZone("GMT+13")); // Prints 2011-10-06 16:35:05 GMT+13:00 System.out.println(formatter.format(calendar.getTime()));