Parlant de l'heure d'été, il a été question d'introduire l'heure d'été comme mesure contre la chaleur des Jeux Olympiques. C'était impossible, et cette histoire s'est déroulée telle quelle. Tant que j'étais au Japon, je pensais que l'été n'avait rien à voir avec ça, mais au Japon j'ai marché sur un bug causé par l'été. Cet article en est la fin.
J'exécutais une boucle comme celle-ci pour créer des données sur les dates:
Calendar cal = new GregorianCalendar(1900, 1 - 1, 1, 0, 0, 0);
Calendar end = new GregorianCalendar(2020, 12 - 1, 31, 0, 0, 0);
long endTime = end.getTimeInMillis();
while (cal.getTimeInMills() <= endtime) {
// (Date de création des données)
cal.add(Calendar.DATE, 1);
}
J'essaie de créer des données du 01/01/1900 au 31/12/2020. Cependant, la date de création des données est inférieure d'un jour. Les données devraient être créées jusqu'au 31/12/2020, mais uniquement jusqu'au 30/12/2020. Alors quand je regarde le contenu de la date,
1900/01/01 00:00:00.000
1900/01/02 00:00:00.000
1900/01/03 00:00:00.000
(Omission)
2020/12/28 01:00:00.000
2020/12/29 01:00:00.000
2020/12/30 01:00:00.000
Quelque part par une heure. «End time» indiquait 2020/12/31 00: 00: 00.000, il semble donc que le résultat soit un jour de moins.
Cela s'est produit sur jdk-8u191, mais cela ne s'est pas produit sur les anciens JDK.
1900/01/01 00:00:00.000
1900/01/02 00:00:00.000
1900/01/03 00:00:00.000
(Omission)
2020/12/28 00:00:00.000
2020/12/29 00:00:00.000
2020/12/30 00:00:00.000
2020/12/31 00:00:00.000
Et cela fonctionne comme prévu. Si vous regardez plus en détail,
J'ai découvert. Le dégraissant s'est-il mélangé au JDK pendant ce temps? J'ai traversé diverses choses, mais je n'ai pas trouvé de pages comme celle-ci. Puis, quand j'ai levé les yeux là où il était,
1948/04/29 00:00:00.000
1948/04/30 00:00:00.000
1948/05/01 00:00:00.000
1948/05/02 01:00:00.000
1948/05/03 01:00:00.000
1948/05/04 01:00:00.000
Il est éteint à 1948/05/02. J'ai pensé, et quand je me promenais pendant l'été au Japon
[Période de demande de l'heure d'été](https://ja.wikipedia.org/wiki/%E5%A4%8F%E6%99%82%E5%88%BB%E6%B3%95#%E5%A4%8F% E6% 99% 82% E9% 96% 93% E9% 81% A9% E7% 94% A8% E6% 9C% 9F% E9% 96% 93)
Il coïncide avec le premier jour de l'heure d'été au Japon, le 2 mai 1948. Cela s'est-il produit parce que l'heure d'été japonaise a été implémentée dans jdk-8u171? ?? ??
Je ne trouve aucune description de l'heure d'été au Japon en consultant Change log of jdk-8u171.
En regardant Versions des données de fuseau horaire dans le logiciel JRE, il y a eu des changements liés au Japon vers 2014. Peut être lu, mais il n'y a rien de tel dans jdk-8u171.
Si vous regardez de plus près le journal des modifications de jdk-8u171 ci-dessus, vous trouverez la description suivante.
IANA Data 2018c JDK 8u171 contains IANA time zone data version 2018c. For more information, refer to Timezone Data Versions in the JRE Software.
Les données du fuseau horaire ont été mises à jour. Donc, je vais essayer de frapper ceci.
https://www.iana.org/time-zones
Semble être la source des données de fuseau horaire. En regardant la différence entre tzdb-2018c
et la précédente tzdb-2018b
,
tzdb-2018b
2018-01-18 08:50 asia:
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Japan 1948 only - May Sun>=1 2:00 1:00 D
Rule Japan 1948 1951 - Sep Sat>=8 2:00 0 S
Rule Japan 1949 only - Apr Sun>=1 2:00 1:00 D
Rule Japan 1950 1951 - May Sun>=1 2:00 1:00 D
tzdb-2018c
2018-01-23 10:30 asia:
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Japan 1948 only - May Sat>=1 24:00 1:00 D
Rule Japan 1948 1951 - Sep Sat>=8 25:00 0 S
Rule Japan 1949 only - Apr Sat>=1 24:00 1:00 D
Rule Japan 1950 1951 - May Sat>=1 24:00 1:00 D
Et il y a certainement des changements. Comment lire ceci
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Japan 1948 only - May Sun>=1 2:00 1:00 D
(Premier samedi de mai 1948(Premier samedi après le 1er)sur 2:Avancez à 00 pendant 1 heure)
Il paraît que. Le nouveau est
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Japan 1948 only - May Sun>=1 24:00 1:00 D
(Premier samedi de mai 1948(Premier samedi après le 1er)24:Avancez à 00 pendant 1 heure)
Et l'heure de début de l'heure d'été a été modifiée. En d'autres termes, si vous changez 0 heure en 1 heure. Ah!
jdk-8u171 a une mise à jour de l'heure d'été du Japon. Cela change l'heure de début de l'heure d'été de 2 heures à 0 heures. Puisque le programme original fonctionnait à 00: 00: 00
Était hors d'une heure. Jusque-là, l'heure de début était 2h00, donc
Du coup, j'ai pu calculer la date sans la perdre.
Puisque la cause a été élucidée, c'est une contre-mesure. Comment surmonter ce problème.
Puisque l'heure de fin était le 31/12/2018 à 00:00:00, c'était un jour de moins. N'y a-t-il pas de problème si cela est défini sur 2018/12/31 23:59:59?
Calendar end = new GregorianCalendar(2020, 12 - 1, 31, 0, 0, 0);
end.add(Calendar.DATE, 1)
end.add(Calendar.MILLISECOND, -1)
long endTime = end.getTimeInMillis(); // 2018/12/31 23:59:59.999
Ce correctif a certainement fonctionné comme prévu. Cependant, il est vraiment désagréable que la date sur le chemin indique 01:00:00. Même si cela fonctionne ici, cela peut poser des problèmes ailleurs.
Puisqu'il s'agit de cal.add (Calender.DATE, 1), il sera décalé, et s'il s'agit de cal.add (Calender.HOUR, 24), il ne sera pas décalé. Bien sûr, le programme fonctionnait toujours comme prévu. Cependant, si vous regardez l'heure
1948/04/29 00:00:00.000
1948/04/30 00:00:00.000
1948/05/01 00:00:00.000
1948/05/02 01:00:00.000
1948/05/03 01:00:00.000
1948/05/04 01:00:00.000
...
1948/09/09 01:00:00.000
1948/09/10 01:00:00.000
1948/09/11 01:00:00.000
1948/09/12 00:00:00.000
1948/09/13 00:00:00.000
1948/09/14 00:00:00.000
Après tout, c'est parti. Donc, le même problème se produit si la date de fin est le 09/09/1948. Il est peu probable que cela se produise en pratique, mais c'est un bug potentiel et j'aimerais l'éviter si possible.
Que diriez-vous de toujours régler l'heure à 00: 00: 00.000 après +1 jour?
cal.add(Calendar.DATE, 1);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Puis
1948/04/29 00:00:00.000
1948/04/30 00:00:00.000
1948/05/01 00:00:00.000
1948/05/02 01:00:00.000 //Ça ne peut pas être aidé ici
1948/05/03 00:00:00.000
1948/05/04 00:00:00.000
...
1948/09/09 00:00:00.000
1948/09/10 00:00:00.000
1948/09/11 00:00:00.000
1948/09/12 00:00:00.000
1948/09/13 00:00:00.000
1948/09/14 00:00:00.000
C'est l'opération prévue. Cependant, il semble redondant de définir 00: 00: 00.00 à chaque fois. Je travaille rarement avec les données de 1948, donc je ne veux pas pouvoir effacer l'heure à chaque fois.
Ensuite, je suis arrivé à utiliser LocalDate. Il s'agit de l'une des API de date et d'heure introduite depuis Java8. LocalDate est une classe de date uniquement sans informations d'heure, elle n'est donc pas affectée par l'heure d'été. Le code précédent est
LocalDate cal = LocalDate.of(1900, 1, 1);
LocalDate end = LocalDate.of(2018, 12, 31);
long endDay = end.toEpochDay();
while (cal.toEpochDay() <= endDay) {
// (Date de création des données)
cal = cal.plusDays(1); //LocalDate est immuable
}
Vous pouvez simplement le mettre dans le code tel quel sans aucune solution de contournement.
Il semble que le problème soit que le bon sens ne s'applique pas quand il y a l'heure d'été comme suit.
Je pensais que c'était du bon sens. Jusqu'à ce que vous marchiez sur ce bogue. .. ..
J'espère que l'heure d'été ne sera plus introduite au Japon à l'avenir.