Index: trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 17103)
+++ trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 17104)
@@ -10,4 +10,5 @@
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
 import java.util.Date;
 import java.util.Locale;
@@ -15,10 +16,6 @@
 import java.util.concurrent.TimeUnit;
 
-import javax.xml.datatype.DatatypeConfigurationException;
-import javax.xml.datatype.DatatypeFactory;
-
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.UncheckedParseException;
 
@@ -44,16 +41,4 @@
     public static final BooleanProperty PROP_ISO_DATES = new BooleanProperty("iso.dates", false);
 
-    private static final DatatypeFactory XML_DATE;
-
-    static {
-        DatatypeFactory fact = null;
-        try {
-            fact = DatatypeFactory.newInstance();
-        } catch (DatatypeConfigurationException e) {
-            Logging.error(e);
-        }
-        XML_DATE = fact;
-    }
-
     /**
      * Constructs a new {@code DateUtils}.
@@ -70,5 +55,5 @@
      * @throws DateTimeException if the value of any field is out of range, or if the day-of-month is invalid for the month-year
      */
-    public static synchronized Date fromString(String str) {
+    public static Date fromString(String str) {
         return new Date(tsFromString(str));
     }
@@ -81,7 +66,14 @@
      * @throws DateTimeException if the value of any field is out of range, or if the day-of-month is invalid for the month-year
      */
-    public static synchronized long tsFromString(String str) {
+    public static long tsFromString(String str) {
         // "2007-07-25T09:26:24{Z|{+|-}01[:00]}"
-        if (checkLayout(str, "xxxx-xx-xxTxx:xx:xxZ") ||
+        if (checkLayout(str, "xxxx-xx-xx")) {
+            final ZonedDateTime local = ZonedDateTime.of(
+                    parsePart4(str, 0),
+                    parsePart2(str, 5),
+                    parsePart2(str, 8),
+                    0, 0, 0, 0, ZoneOffset.UTC);
+            return local.toInstant().toEpochMilli();
+        } else if (checkLayout(str, "xxxx-xx-xxTxx:xx:xxZ") ||
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx") ||
                 checkLayout(str, "xxxx:xx:xx xx:xx:xx") ||
@@ -136,6 +128,7 @@
 
         try {
-            return XML_DATE.newXMLGregorianCalendar(str).toGregorianCalendar().getTimeInMillis();
-        } catch (IllegalArgumentException ex) {
+            // slow path for fractional seconds different from millisecond precision
+            return Instant.parse(str).toEpochMilli();
+        } catch (IllegalArgumentException | DateTimeParseException ex) {
             throw new UncheckedParseException("The date string (" + str + ") could not be parsed.", ex);
         }
@@ -158,5 +151,5 @@
      * @since 14434
      */
-    public static synchronized String fromTimestampInMillis(long timestamp) {
+    public static String fromTimestampInMillis(long timestamp) {
         final ZonedDateTime temporal = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.UTC);
         return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(temporal);
@@ -168,5 +161,5 @@
      * @return The formatted date
      */
-    public static synchronized String fromTimestamp(int timestamp) {
+    public static String fromTimestamp(int timestamp) {
         return fromTimestamp(Integer.toUnsignedLong(timestamp));
     }
@@ -177,5 +170,5 @@
      * @return The formatted date
      */
-    public static synchronized String fromDate(Date date) {
+    public static String fromDate(Date date) {
         final ZonedDateTime temporal = date.toInstant().atZone(ZoneOffset.UTC);
         return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(temporal);
