0

I wrote a DateUtil class that converts java.time.LocalDateTime to java.util.Date and backwards. When trying to get the system-Default TimeZone or a specific TimeZone (Europe/Berlin) I get an exception. I checked that the JVM TimeZone is correctly configured, and it is.

Here is my simple code:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class DateUtil {
    public static Date toDate(LocalDateTime dateTime) {
        System.out.println(System.getProperty("user.timezone"));
        ZoneId zone = ZoneId.of("Europe/Berlin");
        return Date.from(dateTime.atZone(zone).toInstant());
    }

    public static Date toDate(LocalDate date) {
        return Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }
}

This is the exception:

java.time.zone.ZoneRulesException: Invalid binary time-zone data: TZDB:Europe/Berlin, version: 2019c
    at java.time.zone.TzdbZoneRulesProvider.provideRules(TzdbZoneRulesProvider.java:141)
    at java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:227)
    at java.time.ZoneRegion.ofId(ZoneRegion.java:120)
    at java.time.ZoneId.of(ZoneId.java:411)
    at java.time.ZoneId.of(ZoneId.java:359)
    at de.swkbank.camunda.ks.smarta.util.DateUtil.toDate(DateUtil.java:11)
    at de.swkbank.camunda.ks.smarta.delegate.WorkingHoursCalculator.getNextDate(WorkingHoursCalculator.java:16)
    at de.swkbank.camunda.ks.smarta.delegate.WorkingHoursCalculatorTest.test(WorkingHoursCalculatorTest.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.NullPointerException
    at java.time.zone.ZoneOffsetTransition.getDateTimeAfter(ZoneOffsetTransition.java:287)
    at java.time.zone.ZoneRules.<init>(ZoneRules.java:292)
    at java.time.zone.ZoneRules.readExternal(ZoneRules.java:456)
    at java.time.zone.Ser.readInternal(Ser.java:194)
    at java.time.zone.Ser.read(Ser.java:188)
    at java.time.zone.TzdbZoneRulesProvider.provideRules(TzdbZoneRulesProvider.java:136)
    ... 40 more

Is there some misconfiguration on my computer? Its a Microsoft Surface with Win 10. JVM is RedHat JDK 1.8.0.242

double-beep
  • 5,031
  • 17
  • 33
  • 41
Lukas Bard
  • 41
  • 5
  • This error is not reproducible, on my machine this runs without an exception. Try a different JDK. – deHaar Jul 05 '21 at 08:08
  • 3
    "When trying to get the system-Default TimeZone" - so even a simple `ZoneId.systemDefault()` produces that NPE and even in an otherwise empty application? If so, could you post that as a [mcve] and maybe state some more info on your system/JVM setup? Did you try with another JVM? – Thomas Jul 05 '21 at 08:13
  • I updated JVM to 1.8.0.292 (Red Hat). Still same error. – Lukas Bard Jul 05 '21 at 08:41
  • 1
    Post an [MCVE](https://stackoverflow.com/help/minimal-reproducible-example). – Basil Bourque Jul 05 '21 at 09:17
  • See your [code run live at IdeOne.com](https://ideone.com/6KVOLO) – Basil Bourque Jul 05 '21 at 09:30

2 Answers2

2

Not sure what is going wrong exactly. But there seems to be a problem, perhaps corruption, in the tzdb (time zone database) that defines the time zones.

And your tzdb is out-of-date at version 2019c. I suggest you update your tzdb in your JDK, or just replace your entire JDK with a later version. Either way, you may see your error disappear.


By the way, you should try to phase out your use of Date and Calendar classes wherever possible. The java.time classes are intended to replace the legacy classes entirely. Convert back and forth where you must, to interface with old code not yet updated to java.time. But try to move on when you can. Those old classes really are that bad.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

The problem occured when mocking LocalDateTime::now. This results in the exception. I could solve the mocking by injecting a java.time.Clock to the now-Call and returning a fixed clock in the test.

Lukas Bard
  • 41
  • 5
  • 1
    Happens if you have `try (MockedStatic mockedLocalDateTime = Mockito.mockStatic(LocalTime.class)) { mockedLocalDateTime.when(() -> LocalTime.now(ZoneId.of("America/New_York"))).thenReturn(currentTime); assert()...` Trick is to extract - `ZoneId.of("America/New_York")` outside static context of the test(outside try in my case) – visrahane Apr 05 '23 at 18:32
  • i am using a clock & it's already outside of the clock. i still see the error. thanks for the post anyway. it's good to know the cause. – Mag Musik May 29 '23 at 04:42