[JAVA] Problème d'été aussi au Japon

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.

Un jour de moins pour une raison quelconque

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.

Ne se produit pas avec les anciens JDK

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? ?? ??

Journal des modifications JDK

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.

Données d'heure d'été (données de fuseau horaire)

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!

Que se passait-il

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.

Contre-mesures

Puisque la cause a été élucidée, c'est une contre-mesure. Comment surmonter ce problème.

Réglez l'heure de fin sur +1 jour-1 milliseconde

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.

+24 heures

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.

+1 jour .set (00:00:00)

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.

Utiliser LocalDate

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.

Quel était le problème après tout?

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. .. ..

finalement

J'espère que l'heure d'été ne sera plus introduite au Japon à l'avenir.

Recommended Posts

Problème d'été aussi au Japon
À propos de l'heure d'été réelle
Comment régler l'heure d'affichage sur l'heure japonaise dans les rails
Diverses pensions au Japon