Fix test.xml timestamps to produce ISO8601 irrespective of locale or timezone

Test.xml timestamps always reported as ISO8601 UTC timestamps.

RELNOTES: None.
PiperOrigin-RevId: 257840403
diff --git a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestInterval.java b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestInterval.java
index 29abdc4..7efaeff 100644
--- a/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestInterval.java
+++ b/src/java_tools/junitrunner/java/com/google/testing/junit/runner/model/TestInterval.java
@@ -16,8 +16,7 @@
 
 import com.google.testing.junit.runner.util.TestClock.TestInstant;
 import java.time.format.DateTimeFormatter;
-import java.util.Locale;
-import java.util.TimeZone;
+import java.time.format.DateTimeFormatterBuilder;
 
 /**
  * Implementation of an immutable time interval, representing a period of time between two instants.
@@ -27,7 +26,7 @@
 public final class TestInterval {
 
   private static final DateTimeFormatter ISO8601_WITH_MILLIS_FORMATTER =
-      DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXXX");
+      new DateTimeFormatterBuilder().appendInstant(3).toFormatter();
   private final TestInstant startInstant;
   private final TestInstant endInstant;
 
@@ -56,17 +55,9 @@
   }
 
   public String startInstantToString() {
-    // Format as ISO8601 string
-    return startInstantToString(TimeZone.getDefault(), Locale.getDefault());
-  }
-
-  /** Exposed for testing because java Date does not allow setting of timezones and locale. */
-  // VisibleForTesting
-  String startInstantToString(TimeZone tz, Locale locale) {
-    return ISO8601_WITH_MILLIS_FORMATTER
-        .withZone(tz.toZoneId())
-        .withLocale(locale)
-        .format(startInstant.wallTime());
+    // Format as ISO8601 with 3 fractional digits on seconds
+    // This format is not affected by timezones and locale which improves interoperability
+    return ISO8601_WITH_MILLIS_FORMATTER.format(startInstant.wallTime());
   }
 
   /** Returns a TestInterval that contains both TestIntervals passed as parameter. */
diff --git a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java
index 8afa347..ff0eb3d 100644
--- a/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java
+++ b/src/java_tools/junitrunner/javatests/com/google/testing/junit/runner/model/TestIntervalTest.java
@@ -20,9 +20,6 @@
 import com.google.testing.junit.runner.util.TestClock.TestInstant;
 import java.time.Duration;
 import java.time.Instant;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -83,17 +80,9 @@
 
   @Test
   public void testDateFormat() {
-    Date date = new Date(1471709734000L);
-    TestInterval interval =
-        new TestInterval(
-            testInstant(date.toInstant()), testInstant(date.toInstant().plusMillis(100)));
-    assertThat(interval.startInstantToString(TimeZone.getTimeZone("America/New_York"), Locale.US))
-        .isEqualTo("2016-08-20T12:15:34.000-04:00");
-    assertThat(interval.startInstantToString(TimeZone.getTimeZone("GMT"), Locale.UK))
-        .isEqualTo("2016-08-20T16:15:34.000Z");
-    assertThat(
-            interval.startInstantToString(
-                TimeZone.getTimeZone("Asia/Bangkok"), new Locale("th", "TH")))
-        .isEqualTo("2016-08-20T23:15:34.000+07:00");
+    Instant start = Instant.ofEpochMilli(1471709734000L);
+    Instant end = start.plusMillis(100);
+    TestInterval interval = new TestInterval(testInstant(start), testInstant(end));
+    assertThat(interval.startInstantToString()).isEqualTo("2016-08-20T16:15:34.000Z");
   }
 }