When dealing with a time zone using java.util.Date in Java, I think that it is common that the date and time are the elapsed time (milliseconds) from the epoch time and the time zone is managed by GMT. , Here we assume that the date and time and the timezone are kept separate for some reason. For example, it looks like this
item | value |
---|---|
Date and time | 2016-12-01 15:00:00 |
Time zone | Australia/Sydney |
When this is displayed by System.out.println etc., the value held by Date type feels strange as shown below. In other words, I want 15:00 to be Australia / Sydney time, but for some reason it's a local time zone. It's like that.
Thu Dec 01 15:00:00 JST 2016
sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=32400000,dstSavings=0,useDaylight=false,transitions=10,lastRule=null]
Also, ** If you use the conversion done here, you will run a bug, so on the other hand, please do not reach this logic as a teacher. ** If you find a solution, I will post it again. I'm not sure if the situation is avoided.
Anyway, I'm thinking about how to keep it as correct data when the above situation occurs. Avoiding such situations may be the best solution.
It's a little tricky code. It's a painstaking measure to convert it to a character string.
TimezoneConversion.java
static Date convertWithBeforeJava7(Date dateTime, TimeZone timeZone) throws ParseException {
String format = "yyyy/MM/dd HH:mm:ss.SSS";
SimpleDateFormat local = new SimpleDateFormat(format);
SimpleDateFormat convert = new SimpleDateFormat(format);
convert.setTimeZone(timeZone);
return convert.parse(local.format(dateTime));
}
Java8
I can't get used to it, but I also tried it in Java 8 classes. It's refreshing somehow, but I also feel like I'm going to go back to the Date type.
I did two types of tests. The input is as follows.
item | value |
---|---|
Local time zone | Australia/Sydney |
Test number | Date and time | Time zone |
---|---|---|
1 | 2016-10-02 02:00 | Australia/Sydney |
2 | 2016-10-02 02:00 | America/Montreal |
Please note that it is not a sufficient test. The result is as follows.
java.lang.AssertionError: It would be same date
Expected: is <Sun Oct 02 17:00:00 EST 2016>
but: was <Sun Oct 02 18:00:00 EST 2016>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:956)
at com.nekoscape.java.sample.TimezoneConversionTest.convertWithOtherTimezone_test_for_Java8Method(TimezoneConversionTest.java:76)
(abridgement)
java.lang.AssertionError: It would be same date
Expected: is <Sun Oct 02 17:00:00 EST 2016>
but: was <Sun Oct 02 18:00:00 EST 2016>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:956)
at com.nekoscape.java.sample.TimezoneConversionTest.convertWithOtherTimezone_test_for_beforeJava7Method(TimezoneConversionTest.java:62)
(abridgement)
Process finished with exit code -1
Two tests have failed. Both occur when you specify America / Montreal, which is not a local timezone. What's happening?
The bottom line is that this logic now has problems when the local timezone is in daylight saving time. The date and time specified as 2016-10-02 02:00 is the start date and time of daylight saving time in Australia / Sydney. Therefore, when it is retained as Date type from the character string, it already means 2016-10-02 03:00. As a result, there is an hour of conversion error.
As mentioned at the beginning, it is a bug. I haven't solved it. Please do not copy even if you make a mistake. The source is placed below so that you can try it out. Source code: timezone-conversion
Recommended Posts