40

How do I set the timezone for unit tests in maven surefire on Java 8?

With Java 7 this used to work with systemPropertyVariables like in the following configuration, but with Java 8 the tests just use the system timezone.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <systemPropertyVariables>
      <user.timezone>UTC</user.timezone>
    </systemPropertyVariables>

Why is that, and how do I fix it?

Wouter Coekaerts
  • 9,395
  • 3
  • 31
  • 35
  • Use the full `Etc/UTC` instead of just `UTC` because three-letter time zone abbreviations are considered deprecated since they can cause [confusion](https://errorprone.info/bugpattern/ThreeLetterTimeZoneID). – Leponzo Dec 24 '22 at 18:25

1 Answers1

79

Short answer

Java now reads user.timezone earlier, before surefire sets the properties in systemPropertyVariables. The solution is to set it earlier, using argLine:

<plugin>
  ...
  <configuration>
    <argLine>-Duser.timezone=UTC</argLine>

Long answer

Java initializes the default timezone, taking user.timezone into account the first time it needs it and then caches it in java.util.TimeZone. That now happens already when reading a jar file: ZipFile.getZipEntry now calls ZipUtils.dosToJavaTime which creates a Date instance that initializes the default timezone. This is not a surefire-specific problem. Some call it a bug in JDK7. This program used to print the time in UTC, but now uses the system timezone:

import java.util.*;

class TimeZoneTest {
  public static void main(String[] args) {
    System.setProperty("user.timezone", "UTC");
    System.out.println(new Date());
  }
}

In general, the solution is to specify the timezone on the command line, like java -Duser.timezone=UTC TimeZoneTest, or set it programmatically with TimeZone.setDefault(TimeZone.getTimeZone("UTC"));.

Full'ish example:

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        ... could specify version, other settings if desired ...
        <configuration>
          <argLine>-Duser.timezone=UTC</argLine>
        </configuration>
      </plugin>
    </plugins>
  </build>
rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Wouter Coekaerts
  • 9,395
  • 3
  • 31
  • 35
  • 1
    Uhm, if you use Java 8, why use `Date` at all? Use the new `DateTime`, `LocalDateTime` etc – fge May 05 '14 at 06:33
  • 6
    @fge That's irrelevant, `new Date()` is just a simple example to be able to compare with Java 7. The new time classes use the same default timezone, so they have exactly the same problem. – Wouter Coekaerts May 05 '14 at 06:44
  • 3
    It's weird that `mvn -Duser.timezone=UTC` doesn't work either. Only `` works. – Sanghyun Lee Sep 09 '15 at 06:53
  • 18
    Setting `TimeZone.setDefault(TimeZone.getTimeZone("UTC"));` in `@Before` worked for me. argLine didn't not sure why. On junit4.10 and mvn3 – zengr May 16 '16 at 23:18
  • We can use -Duser.timezone="Europe/London" also – Manu Dec 09 '16 at 07:38
  • 1
    add user.timezone in MAVEN_OPTS eg: export MAVEN_OPTS=-Duser.timezone=GMT+8 – qxo Mar 23 '17 at 05:02
  • 1
    For me this worked. If it works command line but not IntelliJ (and jacoco is also at play) see http://stackoverflow.com/a/29975159/32453 or use the @Before workaround from zengr's comment... – rogerdpack Jan 23 '19 at 18:59
  • 5
    @SanghyunLee That applies the system property to the Maven process. By default, Surefire / Failsafe will run tests in a separate process. See "Forked Test Execution" [here](https://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html) – Jason Young Apr 01 '19 at 23:11
  • element is not allowed? – slashdottir Jul 15 '19 at 19:20
  • 1
    WARNING: Be careful not to override the javaagent argLine, or risk spending hours to figure out why jacoco no longer works for instance... – BitfulByte Jul 08 '22 at 16:47
  • Use the full `Etc/UTC` instead of just `UTC` because three-letter time zone abbreviations are considered deprecated since they can cause [confusion](https://errorprone.info/bugpattern/ThreeLetterTimeZoneID). – Leponzo Dec 24 '22 at 18:25