java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work.
@Test
void doesNotFallBackToMinus8InNovember2020() {
ZoneId whitehorse = ZoneId.of("America/Whitehorse");
ZoneOffset offsetAtAbsentTransition
= LocalDateTime.of(2020, Month.NOVEMBER, 1, 1, 0)
.atZone(whitehorse)
.withLaterOffsetAtOverlap()
.getOffset();
assertEquals(ZoneOffset.ofHours(-7), offsetAtAbsentTransition);
}
In the same way for America/Dawson.
On my JUnit 5 the test fails:
org.opentest4j.AssertionFailedError: expected: <-07:00> but was: <-08:00>
at org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:195)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:184)
at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:179)
at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1124)
(many more lines)
This is because I haven’t got the latest update to the time zone database.
My Java erroneously “thinks” that the clock is turned back from 2 AM to 1 AM on November 1. This is the error that you want the test to catch. So the wall clock will show 01:00 twice, once with offset -07:00 (correct) and once with offset -08:00 (wrong). To catch the wrong one, we need to use withLaterOffsetAtOverlap()
. On an updated Java installation this call will not make any difference because there won’t be any overlap.
Edit: You may of course also take a date in the middle of the winter rather than the exact time of when the transition is not supposed to happen. I’d probably do both, just in case.
Edit 2:
i need the above code in java 7. how can we write the same in java 7
You use ThreeTen Backport, that backport of java.time, the modern Java date and time API, to Java 6 and 7. Then you just use exactly the same code. See the links at the bottom for the backport. You don’t need to upgrade your production code to java.time (even though there would be advantages of doing so) in order to use java.time in (one of) your unit tests.
As you said after updating to new time zone database the assert
statement works??
It should. I didn’t try myself, but that was the idea.
Question: How to use the backport of java.time with Java 7?
java.time just requires at least Java 6.
- In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
- In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
- On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from
org.threeten.bp
with subpackages.
Edit 3: Joda-Time
i want to use joda time istead of java.time but iam struggling at
getting getoffset as you written in the code. could you please tell me
that the same code in joda time
I really see no compelling reason why you should want to use Joda-Time for this when you can use ThreeTen Backport and thus java.time, the successor of Joda-Time. From the Joda-Time home page:
Note that from Java SE 8 onwards, users are asked to migrate to
java.time
(JSR-310) - a core part of the JDK which replaces this
project.
I know you’re using Java 7; but if you are adding an external dependency to your tests, why not add the best and most modern one you can get?
In any case, here’s an equivalent JUnit 4 test for Joda-Time:
@Test
public void test() {
DateTimeZone timezone = DateTimeZone.forID("America/Whitehorse");
Instant dt = new DateTime(2020, 11, 1, 1, 0, timezone)
.withLaterOffsetAtOverlap()
.toInstant();
long offsetInMilliseconds = timezone.getOffset(dt.getMillis());
assertEquals(TimeUnit.HOURS.toMillis(-7), offsetInMilliseconds);
}
Again, on Joda-Time 2.9.9 and Java 7 it fails:
java.lang.AssertionError: expected:<-25200000> but was:<-28800000>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
(etc.)
You notice that the failure message includes milliseconds values that are somewhat harder to read then the offsets reported in the failure message from the java.time test above.
I am no Joda-Time expert, but if I have understood correctly, Joda-Time keeps its own copy of the time zone database. So upgrading your Java installation is not the right means for getting the test to pass. Instead you need to upgrade your Joda-Time. Instructions are on the Joda-Time website, see the link at the bottom.
Links