When it comes to daylight saving time, there have been talks about introducing daylight saving time as a measure against the heat of the Olympic Games. It was impossible, and this story flowed as it was. As long as I was in Japan, I thought that daylight saving time had nothing to do with it, but I stepped on a bug caused by daylight saving time in Japan. This article is the end of it.
I was running a loop like this to create data about 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 data creation)
cal.add(Calendar.DATE, 1);
}
I am trying to create data from 1900/01/01 to 2020/12/31. However, the date data created is one day less. Data should be created until 12/31/2020, but only until 12/30/2020. So when I look at the contents of the 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
Somewhere off by an hour. ʻEnd time` pointed to 2020/12/31 00: 00: 00.000, so it seems that the result is one day less.
This happened on the jdk-8u191, but it didn't happen on older JDKs.
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
And it works as expected. If you look in more detail,
I found out. Did Degres get mixed in with the JDK during this time? I went through various things, but I couldn't find any pages like this. Then, when I looked up where it was off,
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
It is off at 1948/05/02. I thought, and when I went around in Japan's daylight saving time
[Daylight Saving Time Application Period](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)
It coincides with the first day of daylight saving time in Japan, May 2, 1948. Did this happen because the Japanese summertime was implemented in the jdk-8u171? ?? ??
I can't find any description about daylight saving time in Japan by looking at Changelog of jdk-8u171.
Looking at Timezone Data Versions in the JRE Software, there were changes related to Japan around 2014. Can be read, but there is no such thing in jdk-8u171.
If you take a closer look at the Changelog of jdk-8u171 above, you will find the following description.
IANA Data 2018c JDK 8u171 contains IANA time zone data version 2018c. For more information, refer to Timezone Data Versions in the JRE Software.
Timezone data has been updated. So, I will try to hit this.
https://www.iana.org/time-zones
Seems to be the source of Timezone data. Looking at the difference between tzdb-2018c
and the previous 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
And certainly there are changes. How to read this
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Japan 1948 only - May Sun>=1 2:00 1:00 D
(First Saturday of May 1948(First Saturday after 1st)of 2:Advance to 00 for 1 hour)
It seems that. The new one is
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Japan 1948 only - May Sun>=1 24:00 1:00 D
(First Saturday of May 1948(First Saturday after 1st)24:Advance to 00 for 1 hour)
And the start time of summer time has been changed. In other words, if you change 0 o'clock to 1 o'clock. Ah!
The jdk-8u171 has an update for daylight saving time in Japan. This changes the start time of daylight saving time from 2 o'clock to 0 o'clock. Since the original program was running at 00:00:00
Was off by one hour. Until then, the start time was 2:00 am, so
As a result, I was able to calculate the date without losing it.
Since the cause has been clarified, it is a countermeasure. How to overcome this problem.
Since the end time was 2018/12/31 00:00:00, it was one day less. Isn't there any problem if this is set to 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
Certainly this fix worked as intended. However, it's really unpleasant that the date on the way points to 01:00:00. Even if it works here, it can cause problems elsewhere.
Since it is cal.add (Calender.DATE, 1), it will be shifted, and if it is cal.add (Calender.HOUR, 24), it will not be shifted. Sure, the program still worked as intended. However, if you look at the time
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
After all it is off on the way. So the same problem occurs if the end date is 09/09/1948. It's unlikely to happen in practice, but it's a potential bug and I'd like to avoid it if possible.
How about always setting the time to 00: 00: 00.000 after +1 day?
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);
Then
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 //There is no help for it here
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
It is the intended operation. However, it feels redundant to set 00: 00: 00.00 every time. I rarely work with 1948 data, so I don't want to be able to clear the time every time.
Then I arrived at using LocalDate. This is one of the Date and Time API introduced from Java8. LocalDate is a date-only class that has no time information, so it is not affected by daylight saving time. The previous code is
LocalDate cal = LocalDate.of(1900, 1, 1);
LocalDate end = LocalDate.of(2018, 12, 31);
long endDay = end.toEpochDay();
while (cal.toEpochDay() <= endDay) {
// (Date data creation)
cal = cal.plusDays(1); //LocalDate is Immutable
}
You can simply put it in the code as it is without taking any workaround.
It seems that the problem is that common sense does not apply when there is daylight saving time as follows.
I thought it was common sense. Until you step on this bug. .. ..
I hope that summer time will not be introduced in Japan in the future.