1. Connaissances de préparation
1. L'heure d'été de la lumière du jour d'Amérique / New_york est la suivante: la gauche n'est pas la droite est
2016-3-13, 02:00:00 à 2016-11-116, 02:00:00
2017-3-12, 02:00:00 à 2017-11-5, 02:00:00
2. ID de fuseau horaire de trois lettres
Pour la compatibilité avec JDK 1.1.x, certains ID de fuseau horaire à trois lettres (tels que "PST", "CTT", "AST") sont également pris en charge.
Cependant, leur utilisation est rejetée car la même abréviation est souvent utilisée dans plusieurs fuseaux horaires
Par exemple, CST: Il a 4 significations, les États-Unis, l'Australie, la Chine, Cuba Time
3. Standard
GMT: Temps moyen vert Greenwich Temps standard, a été utilisé comme référence standard GMT + 12 -> GMT-12 avant 1960
La gamme de Java8 est GMT + 18 -> GMT-18
UTC: Le temps universel coordonné coordonne le temps mondial, qui est plus précis que GMT, et devient la nouvelle norme le 1er janvier 1972; UTC, UTC + 1, UTC + 2 ... UTC + 12, UTC-12 ... UTC-1
Range de Java8 UTC-18 -> UTC + 18
DST: Le temps de référence de la lumière du jour fait référence au temps où l'horloge est tournée pendant une heure en été pour utiliser la lumière du soleil plus tôt. Il s'appelle l'heure d'été au Royaume-Uni;
Actuellement, plus de 110 pays utilisent l'heure d'été;
En Chine, il n'a été mis en œuvre que pendant 6 ans de 1986 à 1992, et il a été annulé par la suite; Les raisons sont les suivantes:
1. La Chine a une grande étendue dans les directions est et ouest et adopte un huitième district unifié, qui est incompatible avec l'est et l'ouest en utilisant l'heure d'été;
2. Dans les zones à haute latitude, le temps du jour et la nuit change considérablement en hiver et en été; Ce n'est pas très significatif;
4. Il peut être utilisé pour indiquer que le huitième district est: GMT + 8 ou etc / GMT-8 (juste l'inverse, pourquoi? Parce que les développeurs PHP croient que le huitième district est 8 heures plus rapidement que l'heure standard, et devrait être soustraite de 8 heures, donc la représentation est comme celle-ci. Différents objets de référence ont conduit à différentes méthodes de représentation;);)
5. Comment représenter le fuseau horaire de la Chine
GMT + 8
UTC + 8
Asie / Harbin Harbin // Chine Heure standard
Asie / Chongqing Chongqing // Chine Temps standard
Asie / Chungking Chongqing // Chine Temps standard
Asie / Urumqi Urumqi // Chine Temps standard
Asie / Shanghai Shanghai (East 8 District) // Chine Standard Time
RPC
Asie / Macao Macau // Chine Temps standard
Hongkong Hong Kong // Le temps de Hong Kong est conforme à l'heure standard de la Chine
Asie / Hong_kong Hong Kong
Asie / Taipei Taipei (Taiwan) // Chine Standard Time Singapour est le même que le temps de la Chine;
Asie / Singapour
Singapour
6. Représentation des fuseaux horaires standard
UTC
UTC + 0
UTC-0
GMT GMT
GMT0 GMT
Etc / gmt gmt
Etc / gmt + 0 gmt
Etc / gmt-0 GMT
Etc / GMT0 GMT0 GMTS Temps normal Remarque: GMT + XX (-XX) est très inclusif et peut identifier automatiquement la représentation de divers temps.
2. Conversion du fuseau horaire
Environnement: avant Java8
1. Convertissez l'heure actuelle en affichage de fuseau horaire spécifié
@Test public void test () lève une exception {date a = new Date (); SimpledateFormat sf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); sf.setTimeZone (timezone.getTimeZone ("America / New_york")); // convertir le fuseau horaire chinois en fuseau horaire de New York du système américain.out.println (sf.format (a)); }2. Le temps spécifié est converti à l'affichage du fuseau horaire spécifié
Puis-je vraiment convertir correctement? Il semble y avoir un piège, j'ai regardé la mise en œuvre en ligne
Je ressens un peu de problème avec l'heure d'été
// Méthode d'implémentation 1: l'heure d'été de la lumière du jour n'est pas considérée comme @Test public void test2 () lève une exception {/ date dateTime = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"). Parse ("2016-11-6 14:00:00"); Date DateTime = new SimpledateFormat ("Yyyy-mm-dd HH: MM: SS"). Parse ("2016-10-6 14:00:00"); Timezone Zhong = Timezone.getTimeZone ("GMT + 8: 00"); // China Timezone York = Timezone.getTimeZone ("America / New_york"); // gmt-5 // Le décalage du fuseau horaire ici est corrigé, il n'y a pas de temps d'été, l'erreur long chinesemills = dateTime.getTime () + York.getRawoffset () - zhong.getrawoffset (); Date de date = nouvelle date (ChineseMILLS); System.out.println (new SimpledateFormat ("Yyyy-mm-dd HH: MM: SS"). Format (date)); } // Méthode d'implémentation 2 Vous vous souvenez peut-être qu'à l'aide de Calendar.dst_offset de la classe Calendar //, il n'est toujours pas juste à Calendar.dst_offset This is Dead @TestPublic void test3 () lance l'exception {// Date Heure = New SimpledateFormat ("Yyyy-mm-dd hh: mm: ss"). Parse ("2016-11-6 14:00:00");); = nouveau simpledateFormat ("yyyy-mm-dd hh: mm: ss"). parse ("2016-11-6 1:00:00"); // date = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"). Parse ("2016-11-6 1:00:00"); // HH: MM: SS "). Parse (" 2016-11-6 0:59:00 "); // Date Heure = new SimpledateFormat (" Yyyy-mm-dd HH: MM: SS "). Parse (" 2016-11-6 1:59:59 "); date de date = new Simpleformat (" Yyy-mm-dd HH: MM: SS "). Parse (" 2016-11-6 3:00:00 "); // 1. Obtenez l'heure locale: Calendar Cal = calendar.getInstance (); Cal.SetTime (Time); Cal.settimeZone (Timezone.getTimeZone (" America / New_york ")); // 2. Obtenez le temps décalé: That is Fixe Cal.get (calendar.zone_offset) / (1000 * 60 * 60); // 3. Obtenez le décalage horaire de la lumière du jour: Ceci est fixé, non basé sur le jugement dynamique du temps. Tant qu'il y a du temps d'été dans le fuseau horaire, il s'agit de 1Int dstoffset = cal.get (calendar.dst_offset) / (1000 * 60 * 60); System.out.println (ZoneOffset); System.out.println (dstoffset); // 4. dédaliser ces différences par rapport à l'heure locale pour obtenir le temps utcale: //cal.add(Calendar. - (ZoneOffset + dstoffset)); cal.add (calendar.hour, - (ZoneOffset + dstoffset)); date time2 = cal.gettime (); System.out.println (new SimpledateFormat (Time2);} // Méthode d'implémentation 3 Préparation // N'est-il pas dit que Java gèrera automatiquement l'heure d'été pour nous? // Allons d'abord un test simple pour voir si la méthode de jugement de temps d'été, et vous pouvez déduire si le traitement automatique de Java est correct // Il est connu qu'en 2016: America / New_ork's Daymuly Time Heure est: 2016-3-13 02:00:00 à 2016-11-06 01:59:59 @Test Public Vee Test4 () Louilles de la zone de référence () Lours SimpledateFormat sf = new SimpledateFormat ("yyyy-mm-dd hh: mm: ss"); sf.setTimeZone (Timezone.getTimeZone ("GMT + 0")); // Date DateTime = SF.Parse ("2016-11-6 5:59:59"); Date D1 = SF.Parse ("2016-03-13 6:59:59"); // False Date D2 = SF.Parse ("2016-03-13 7:00:00"); // Date de vrai D3 = SF.Parse ("2016-11-6 6:59:59"); // FACE D4 = SF.PARSE ("2016-11-6 7:00:00"); //; J'ai constaté qu'il n'y a en effet aucun problème à juger le début de l'heure d'été, mais pour l'heure de fin de l'heure d'été, pour être précise, je l'ai jugée d'heure à l'avance // Regardez la vérification ci-dessous, alors pourquoi est-ce une heure à l'avance? Comment le résoudre? À l'heure actuelle, je ne peux utiliser Java8 D3 = SF.Parse ("2016-11-6 5:59:59"); // true d4 = sf.parse ("2016-11-6 6:00:00"); // False Timezone York = Timezone.getTimeZone ("America / New_york"); // GMT-5 System.out.println ("Le fuseau horaire cible utilise-t-il l'heure d'été:" + Isdaylight (York, D1)); System.out.println ("Le fuseau horaire cible utilise-t-il l'heure d'été:" + Isdaylight (York, D2)); System.out.println ("Le fuseau horaire cible utilise-t-il l'heure d'été:" + Isdaylight (York, D3)); System.out.println ("Le fuseau horaire cible utilise-t-il l'heure d'été:" + Isdaylight (York, D4)); } // juge si privé Boolean Isdaylight (Zone du Zone de temps, date de date) {RETOUR ZONE.USEDAYlightTime () && Zone.IndaylightTime (Date); } // Méthode de mise en œuvre 3 // Grâce à la vérification ci-dessus, nous savons que le jugement du système est problématique. En définissant le fuseau horaire, le programme gère automatiquement l'heure d'été. Au moins je ne comprends pas pourquoi @TestPublic void test5 () lève une exception {// 13 heures d'intervalle Chine + 8 New York-5 ChangeZone ("2016-3-13 14:59:59", "PRC", "America / New_york", "Yyyy-mm-dd HH: MM: SS"); // 2016-03-13 01:59:59 15:00:00 "," PRC "," America / New_york "," Yyyy-mm-dd HH: MM: SS "); // 2016-03-13 03:00:00 ChangeZone (" 2016-11-6 13:59:59 "," PRC "," America / New_york " 01:59:59 // Ce résultat est faux, il devrait être 02:00:00 ChangeZone ("2016-11-6 14:00:00", "PRC", "America / New_york", "Yyyy-mm-dd HH: MM: SS"); // 2016-11-06 01:00 00} // L'implémentation spécifique est comme suivant: // L'idée qui est celle-ci. Time, String Srcid, String Destid, String Match) lève ParseException {// Définissez le fuseau horaire par défaut Zone = TimeZone.GetTimeZone (SRCID); Timezone.setDefault (Zone); Date Date = new SimpledateFormat (modèle) .Parse (heure); // Définissez le fuseau horaire cible du fuseau horaire destZone = Timezone.getTimeZone (Destid); SimpledateFormat sdf = new SimpledateFormat (modèle); // Définissez le fuseau horaire à formater sdf.setTimeZone (destZone); String changtime = sdf.format (date); // Obtenez le Système de fuseau horaire cible.out.println ("après modification du fuseau horaire" + destZone.getID () + "Time:" + Changtime); }Résumé: Les résultats obtenus par les trois méthodes de mise en œuvre ci-dessus sont quelque peu problématiques pour l'heure d'été
Trois, implémentation Java8
1. Jetons un coup d'œil aux changements de fuseau horaire dans Java 8 en premier
// Fuseau horaire disponible de JDK8 @TestPublic void TestName1 () lève l'exception {// JDK8's All Fuseh Zones set <string> ids = ZoneId.getAcAnableZoneid (); String [] id1 = ids.toArray (New String [ids.size ()]); String idsSS = Arrays.Tostring (id1) .replace ("]", " ",]"); System.out.println (ids.size ()); // 28 fuseaux horaires manquants avant la chaîne de JDK8 [] id2 = timezone.getAvailableID (); System.out.println (id2.length); // 623 // Découvrez le For (String id: id2) {if (! Ids.contains (id + ",")) {System.out.print (id + ",");}} // Conclusion: tous les zones horaires dans JDK8 ont toutes été supprimées avant // jdk8 Comme suit: // Il y a des zones de temps qui sont facilement ambigu AGT, ART, AST, BET, BST, CAT, CNT, CST, CTT, EAT, ECT, IET, IST, JST, MIT, NET LocalDateTime.Ofinstant (Instant.Now (), ZoneId.of (ZoneId.Short_ids.get ("PST"))); System.out.println ("/ ndate =" + Date);}2. Comment ajouter des informations de fuseau horaire ou les convertir
// localDate, localDatetime, instantan ajout informations de fuseau horaire @TestPublic void testName3 () {localDate date = localDate.now (); // localDate add informations de fuseau horaire // Méthode 1ZonedDateTime Zone = Date.atstartofday (ZoneId.of (GMT + 08: 00 ")); System.out.PrintLn (Zone); Date.atstartofday (ZoneId.SystemDefault ()); System.out.println (Zone); // Méthode 2 LocalDate Date2 = LocalDate.now (ZoneId.of ("gmt + 0")); System.out.println (date2); System.out.println ("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------. ZoneIime3 = LocalDateTime.Now (Clock.System (ZoneId.of ("GMT + 0"))); // Méthode 4ZonedDateTime ZonEnetime4 = ZonedDateTime.of (Time, ZoneId.of (GMT + 0 ")); System.out.println (Zonetime); System.out.println (ZonEtime3); // Change System.out.println (Zonetime4); // Changement System.out.println ("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------3. Comment obtenir l'heure spécifiée de l'heure actuelle (test omis)
// Obtenez le fuseau horaire spécifié de l'heure actuelle, point de référence: 0 Fuseau horaire public LocalDateTime GetCurrentZonEtime (ZoneId dest) {objets.RequiRenonnull (dest); LocalDateTime time2 = localDateTime.now (Clock.System (dest)); String ZoneDesC = getZoneDesC (timezone.getTimeZone (dest)); System.out.println (dest.getId () + "correspond au fuseau horaire standard:" + zonesec); System.out.println ("Fime Zone cible" + dest + "time" + time2.format (DateTimeFormatter.ofpattern ("Yyyy-mm-dd HH: mm: ss"))); Temps de retour2;} // Obtenez le fuseau horaire standard, méthode 1 // La méthode avant JDK8, utilisez une chaîne statique privée de temps de temps GetZoneDesC (Timezone destZone) {objets.RequiRenonnull (destZone); int offset = destZone.getRawoffset () / (1000 * 60 * 60); if (offset <= 0) {return "gmt" + string.valueof (offset); } else {return "gmt +" + string.valueof (offset); }} // Méthode Java8, méthode 2, utilisez des zonérules // obtenez le décalage standard du fuseau horaire, zonerules.getStandardOffset // Obtenez le décalage réel du fuseau horaire (le décalage obtenu changera en fonction du temps de réduction de la lumière du jour). Rule.getStandardOffset (zonedDateTime.now (dest) .toistant ()). getID (); String s = standardoffset.split (":") [0]; int offset = Integer.ParseInt (s); // Retour Méthode 1: Avec les heures et les minutes // retourner "GMT" + StandardOffset; // Retour Méthode 2: avec des heures seulement si (offset> 0) {return "gmt +" + offset;} else {return "gmt" + offset;}}4. Comment obtenir l'heure spécifiée du fuseau horaire spécifié
Commencez à implémenter le problème du fuseau horaire laissé ci-dessus
De même, examinons d'abord si la méthode de jugement de temps d'été en lumière du jour à l'aide de Java8 est correcte.
// Écrivez une première main pour déterminer si l'heure aux États-Unis est en lumière du jour, l'heure publique Boolean IsdaylightTime (LocalDateTime A) {objets.RequiRenonnull (a); LocalDateTime startDate = A.Withmonth (3) .tolocaldate (). AtTime (2, 0); LocalDatetime startlightday = startDate.with (temporalAdJusters.Dayofweekinmonth (2, dayofweek.sunday)); // Mise à jour de novembre localdatetime enddate = a.withmonth (11) .tolocalate (). Attime (1, 59,59); localDatetime endlightday =. enddate.with (temporalAdJusters.Dayofweekinmonth (1, dayofweek.sunday)); if (a.isbefore (startlightday) || a.isafter (endlightday))) {System.out.println ("Not in Daylight Saufing Time" + a); return false;} System.out.println ("dans le jour de la lumière du jour" + a); Java8 Il existe déjà une méthode prête à l'emploi, qui est meilleure que la mienne // passe dans le temps et le fuseau horaire spécifié Boolean IsdaylightTime (LocalDatetime A, ZoneId dest) {ZonedDatetime Z1 = A.Atzone (dest); // ou transférer de cette façon // ZonedDateTime Z2 = zonedDateTime.of (a, dest); System.out.println (z1.format (DateTimeFormatter.ofpattern ("Yyyy-mm-dd hh: mm: ss"))); Zonerules règles = dest.getRules (); booléen drapeau = règles.isdaylightsavings (z1.toinstant ()); System.out.println (drapeau); drapeau de retour; }// le tester et a constaté que la méthode d'heure d'été de la lumière du jour de Java8 est complètement correcte
// Il est connu que 2016: America / New_Oork's Daylight, l'heure d'été: 2016-3-13 02:00:00 à 2016-11-06 01:59:59 // (le deuxième dimanche de mars et le premier dimanche de novembre chaque année) @Testpublic Void TestName () lance Exception {// LocalDatetime a1 = LocalDatetime.Nownow ();); LocalDateTime A2 = LocalDatetime.of (2016, 3, 13, 1, 59,59); LocalDatetime a3 = localDatetime.of (2016, 3, 13, 2, 00); localDatetime a4 = localDatetime.of (2016, 11, 6, 1, 59,59); localDatetime a5 = localdatetime.of (2016, 11, 6, 2, 0,0);//isDaylightTime(a2);//isDaylightTime(a3);//isDaylightTime(a4);//isDaylightTime(a5);System.out.println("============================== =============================================================. =============================================================. =============================================================. =============================================================. =============================================================. =============================================================. .Commencez à implémenter:
Version 1:
// Obtenez le point de référence de temps spécifié pour le temps spécifié: Fidèle par défaut public LocalDateTime getZongtime (LocalDateTime Time, ZoneId dest) {objets.RequiRenonnull (dest); Retour Getzongtime (Time, Null, Dest); } // Vous ne pouvez pas soustraire de ZonedDateTime de 2 fuseaux horaires, car une fois que vous avez spécifié le fuseau horaire ici, ce temps est ce fuseau horaire localDateTime Getzongtime (LocalDateTime Time, ZoneId SRC, ZoneId dest) {// La difficulté est de savoir comment trouver le décalage // Le fuseau horaire par défaut ici est la Chine, et les États-Unis sont les États-Unis. Ceci est probablement plus adapté aux objets.RequiRenonnull (dest); ZonedDateTime Z1 = null; if (src == null) {z1 = time.atzone (ZoneId.SystemDefault ()); } else {z1 = time.atzone (src); } // La réponse du fuseau horaire change dans le temps zoneddateTime z2 = z1.WithZonesAmEInstant (dest); System.out.println (dest.getId () + "correspond au fuseau horaire standard:" + getZoneDesc (timezone.getTimeZone (dest))); System.out.println ("Target Zone" Target "+ dest +" Time "+ Z2.Format (DateTimeFormatter.ofpattern (" Yyyy-mm-dd hh: mm: ss "))); System.out.println ("-----------------"); heure de retour; }Le test est le suivant:
@Test public void test6 () lève une exception {// il est censé ne pas être en lumière du jour, temps2016-03-13 01:59:59 LocalDatetime Time4 = localDatetime.of (2016, 3, 13, 14, 59, 59); getzongtime (time4, zoneid.of ("America / new_york")); // On s'attend à ce qu'il soit à l'heure d'été 2016-03-13 03:00:00 localDateTime Time1 = LocalDatetime.of (2016, 3, 13, 15, 00, 00); getzongtime (time1, zoneid.of ("America / new_york")); // Le résultat attendu dans l'heure d'été: 2016-11-06 01:59:59 // J'ai l'impression d'avoir échoué à nouveau, ce devrait être 2016-11-06 02:59:59 // En d'autres termes, la méthode avant Java8 gère la fin de la lumière du jour à ce moment-là est la même, et les juges à l'avance // c'est la fin de l'heure du jour du jour, ce qui est ce qui est 2016-11. 00:59:59, mais la méthode de jugement de Java8 est correcte. N'est-ce pas un peu étrange localdatetime time2 = localDateTime.of (2016, 11, 6, 14, 59, 59); getzongtime (time2, zoneid.of ("America / new_york")); // Il ne devrait pas être en lumière du jour l'heure 2016-11-06 02:00:00 LocalDateTime Time3 = LocalDatetime.of (2016, 11, 6, 15, 00, 00); getzongtime (time3, zoneid.of ("America / new_york")); }Je doute donc maintenant que ce résultat soit un problème de calcul systématique, ou je ne comprends pas les coutumes de New York?
Mais je peux toujours obtenir les résultats que je veux, utiliser 2 méthodes:
WithearlierOffSetAtOverlap (), WithlaterOffSetAtOverlap ()
Version 2:
// Obtenez le point de référence du temps spécifié pour l'heure spécifiée: le fuseau horaire par défaut public localDateTime getzongtime2 (localDateItime Time, ZoneId dest) {objets.RequiRenonnull (dest); return getzongtime2 (temps, null, dest);} // version 2 public localdatetime getzongtime2 (LocalDatetime Time to Zoneid Src, Zoneid dest) {la difficulté est le temps, la zoneid Offset // Le fuseau horaire par défaut est utilisé ici, en Chine, aux États-Unis, les États-Unis sont les États-Unis, il est donc probablement plus adapté aux objets.RequiRenonnull (dest); ZonedDateTime Z1 = null; if (src == null) {z1 = time.atzone (ZoneId.SystemDefault ()); } else {z1 = time.atzone (src); } // ZonedDateTime Z2 = z1.WithZonesAmEInstant (dest); // gérer les problèmes de chevauchement longues = durée.between (z2.withearlieroffsetatoverlap (), z2.withlateroffsetatoverlap ()). toOrS (); Z2 = Z2.Plushours (heures); System.out.println (dest.getId () + "correspond au fuseau horaire standard:" + getZoneDesc (timezone.getTimeZone (dest))); System.out.println ("Target Zone" Target "+ dest +" Time "+ Z2.Format (DateTimeFormatter.ofpattern (" Yyyy-mm-dd hh: mm: ss "))); System.out.println ("-------------------"); heure de retour;}Test: ok
@Test public void test4 () lève une exception {// il est censé ne pas être en lumière du jour, temps2016-03-13 01:59:59 LocalDatetime Time4 = localDatetime.of (2016, 3, 13, 14, 59, 59); getzongtime2 (Time4, ZoneId.of ("America / New_york")); // On s'attend à ce qu'il soit à l'heure d'été 2016-03-13 03:00:00 localDateTime Time1 = LocalDatetime.of (2016, 3, 13, 15, 00, 00); getzongtime2 (Time1, ZoneId.of ("America / New_york")); // On s'attend à ce qu'il soit à l'heure d'été 2016-11-06 02:59:59 LocalDatetime Time2 = LocalDatetime.of (2016, 11, 6, 14, 59, 59); getzongtime2 (Time2, ZoneId.of ("America / New_york")); // Il est prévu que l'heure d'été 2016-11-06 02:00:00 LocalDateTime Time3 = LocalDateTime.of (2016, 11, 6, 15, 00, 00); getzongtime2 (Time3, ZoneId.of ("America / New_york")); }résultat:
America / New_york correspond au fuseau horaire standard: GMT-5
Temps du fuseau horaire cible America / New_york 2016-03-13 01:59:59
----------------------
America / New_york correspond au fuseau horaire standard: GMT-5
Temps du fuseau horaire cible America / New_york 2016-03-13 03:00:00
----------------------
America / New_york correspond au fuseau horaire standard: GMT-5
Temps du fuseau horaire cible America / New_York 2016-11-06 02:59:59
----------------------
America / New_york correspond au fuseau horaire standard: GMT-5
Temps du fuseau horaire cible America / New_York 2016-11-06 02:00:00
----------------------
Le problème et la solution ci-dessus pour convertir l'heure d'été en lumière du jour basé sur le fuseau horaire Java est tout le contenu que je partage avec vous. J'espère que vous pourrez vous faire référence et j'espère que vous pourrez soutenir Wulin.com plus.