Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/AdvancedChangesetQueryPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/AdvancedChangesetQueryPanel.java	(revision 11033)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/AdvancedChangesetQueryPanel.java	(revision 11035)
@@ -11,9 +11,12 @@
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
-import java.text.DateFormat;
-import java.text.ParseException;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.FormatStyle;
 import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Locale;
 
 import javax.swing.BorderFactory;
@@ -842,20 +845,16 @@
                 throw new IllegalStateException(tr("Cannot build changeset query with time based restrictions. Input is not valid."));
             if (rbClosedAfter.isSelected()) {
-                GregorianCalendar cal = new GregorianCalendar();
-                Date d1 = valClosedAfterDate1.getDate();
-                Date d2 = valClosedAfterTime1.getDate();
-                cal.setTimeInMillis(d1.getTime() + (d2 == null ? 0 : d2.getTime()));
-                query.closedAfter(cal.getTime());
+                LocalDate d1 = valClosedAfterDate1.getDate();
+                LocalTime d2 = valClosedAfterTime1.getDate();
+                final Date d3 = new Date(d1.atTime(d2).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
+                query.closedAfter(d3);
             } else if (rbClosedAfterAndCreatedBefore.isSelected()) {
-                GregorianCalendar cal = new GregorianCalendar();
-                Date d1 = valClosedAfterDate2.getDate();
-                Date d2 = valClosedAfterTime2.getDate();
-                cal.setTimeInMillis(d1.getTime() + (d2 == null ? 0 : d2.getTime()));
-                Date d3 = cal.getTime();
+                LocalDate d1 = valClosedAfterDate2.getDate();
+                LocalTime d2 = valClosedAfterTime2.getDate();
+                Date d3 = new Date(d1.atTime(d2).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
 
                 d1 = valCreatedBeforeDate.getDate();
                 d2 = valCreatedBeforeTime.getDate();
-                cal.setTimeInMillis(d1.getTime() + (d2 == null ? 0 : d2.getTime()));
-                Date d4 = cal.getTime();
+                Date d4 = new Date(d1.atTime(d2).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
 
                 query.closedAfterAndCreatedBefore(d3, d4);
@@ -1042,5 +1041,5 @@
 
         public String getStandardTooltipText() {
-            Date date = new Date();
+            final ZonedDateTime now = ZonedDateTime.now();
             return tr(
                     "Please enter a date in the usual format for your locale.<br>"
@@ -1049,8 +1048,8 @@
                     + "Example: {2}<br>"
                     + "Example: {3}<br>",
-                    DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()).format(date),
-                    DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).format(date),
-                    DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault()).format(date),
-                    DateFormat.getDateInstance(DateFormat.FULL, Locale.getDefault()).format(date)
+                    DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(now),
+                    DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(now),
+                    DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(now),
+                    DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(now)
             );
         }
@@ -1068,10 +1067,10 @@
         }
 
-        public Date getDate() {
-            for (int format: new int[] {DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL}) {
-                DateFormat df = DateFormat.getDateInstance(format);
+        public LocalDate getDate() {
+            for (final FormatStyle format: FormatStyle.values()) {
+                DateTimeFormatter df = DateTimeFormatter.ofLocalizedDate(format);
                 try {
-                    return df.parse(getComponent().getText());
-                } catch (ParseException e) {
+                    return LocalDate.parse(getComponent().getText(), df);
+                } catch (DateTimeParseException e) {
                     // Try next format
                     Main.trace(e);
@@ -1109,5 +1108,5 @@
 
         public String getStandardTooltipText() {
-            Date date = new Date();
+            final ZonedDateTime now = ZonedDateTime.now();
             return tr(
                     "Please enter a valid time in the usual format for your locale.<br>"
@@ -1116,8 +1115,8 @@
                     + "Example: {2}<br>"
                     + "Example: {3}<br>",
-                    DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(date),
-                    DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.getDefault()).format(date),
-                    DateFormat.getTimeInstance(DateFormat.LONG, Locale.getDefault()).format(date),
-                    DateFormat.getTimeInstance(DateFormat.FULL, Locale.getDefault()).format(date)
+                    DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(now),
+                    DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM).format(now),
+                    DateTimeFormatter.ofLocalizedTime(FormatStyle.LONG).format(now),
+                    DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).format(now)
             );
         }
@@ -1135,16 +1134,18 @@
         }
 
-        public Date getDate() {
+        public LocalTime getDate() {
             if (getComponent().getText().trim().isEmpty())
-                return null;
-
-            for (int style : new int[]{DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL}) {
+                return LocalTime.MIDNIGHT;
+
+            for (final FormatStyle format: FormatStyle.values()) {
+                DateTimeFormatter df = DateTimeFormatter.ofLocalizedTime(format);
                 try {
-                    return DateFormat.getTimeInstance(style, Locale.getDefault()).parse(getComponent().getText());
-                } catch (ParseException e) {
-                    continue;
+                    return LocalTime.parse(getComponent().getText(), df);
+                } catch (DateTimeParseException e) {
+                    // Try next format
+                    Main.trace(e);
                 }
             }
-            return null;
+            return LocalTime.MIDNIGHT;
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/layer/gpx/DateFilterPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/gpx/DateFilterPanel.java	(revision 11033)
+++ trunk/src/org/openstreetmap/josm/gui/layer/gpx/DateFilterPanel.java	(revision 11035)
@@ -7,6 +7,7 @@
 import java.awt.GridBagLayout;
 import java.awt.event.ActionListener;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
 import java.util.Date;
-import java.util.GregorianCalendar;
 
 import javax.swing.JCheckBox;
@@ -49,5 +50,5 @@
         final Date startTime, endTime;
         Date[] bounds = layer.data.getMinMaxTimeForAllTracks();
-        startTime = (bounds.length == 0) ? new GregorianCalendar(2000, 1, 1).getTime() : bounds[0];
+        startTime = (bounds.length == 0) ? Date.from(ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()).toInstant()) : bounds[0];
         endTime = (bounds.length == 0) ? new Date() : bounds[1];
 
Index: trunk/src/org/openstreetmap/josm/io/GpxExporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/GpxExporter.java	(revision 11033)
+++ trunk/src/org/openstreetmap/josm/io/GpxExporter.java	(revision 11035)
@@ -12,5 +12,5 @@
 import java.io.OutputStream;
 import java.text.MessageFormat;
-import java.util.Calendar;
+import java.time.Year;
 
 import javax.swing.JButton;
@@ -225,5 +225,5 @@
                 String sCopyrightYear = data.getString(META_COPYRIGHT_YEAR);
                 if (sCopyrightYear == null) {
-                    sCopyrightYear = Integer.toString(Calendar.getInstance().get(Calendar.YEAR));
+                    sCopyrightYear = Year.now().toString();
                 }
                 copyrightYear.setText(sCopyrightYear);
Index: trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 11033)
+++ trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 11035)
@@ -5,7 +5,10 @@
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
-import java.util.Calendar;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.Date;
-import java.util.GregorianCalendar;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -13,5 +16,4 @@
 import javax.xml.datatype.DatatypeConfigurationException;
 import javax.xml.datatype.DatatypeFactory;
-import javax.xml.datatype.XMLGregorianCalendar;
 
 import org.openstreetmap.josm.Main;
@@ -41,21 +43,7 @@
     public static final BooleanProperty PROP_ISO_DATES = new BooleanProperty("iso.dates", false);
 
-    /**
-     * A shared instance used for conversion between individual date fields
-     * and long millis time. It is guarded against conflict by the class lock.
-     * The shared instance is used because the construction, together
-     * with the timezone lookup, is very expensive.
-     */
-    private static final GregorianCalendar calendar = new GregorianCalendar(UTC);
-    /**
-     * A shared instance to convert local times. The time zone should be set before every conversion.
-     */
-    private static final GregorianCalendar calendarLocale = new GregorianCalendar(TimeZone.getDefault());
     private static final DatatypeFactory XML_DATE;
 
     static {
-        calendar.setTimeInMillis(0);
-        calendarLocale.setTimeInMillis(0);
-
         DatatypeFactory fact = null;
         try {
@@ -97,26 +85,21 @@
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx+xx:00") ||
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx-xx:00")) {
-            final Calendar c; // consider EXIF date in default timezone
-            if (checkLayout(str, "xxxx:xx:xx xx:xx:xx")) {
-                c = getLocalCalendar();
-            } else {
-                c = calendar;
-            }
-            c.set(
+            final ZonedDateTime local = ZonedDateTime.of(
                 parsePart4(str, 0),
-                parsePart2(str, 5)-1,
+                parsePart2(str, 5),
                 parsePart2(str, 8),
                 parsePart2(str, 11),
                 parsePart2(str, 14),
-                parsePart2(str, 17));
-            c.set(Calendar.MILLISECOND, 0);
-
+                parsePart2(str, 17),
+                0,
+                // consider EXIF date in default timezone
+                checkLayout(str, "xxxx:xx:xx xx:xx:xx") ? ZoneId.systemDefault() : ZoneOffset.UTC
+            );
             if (str.length() == 22 || str.length() == 25) {
-                int plusHr = parsePart2(str, 20);
-                int mul = str.charAt(19) == '+' ? -3600000 : 3600000;
-                return c.getTimeInMillis()+plusHr*mul;
+                final int plusHr = parsePart2(str, 20);
+                final int mul = str.charAt(19) == '+' ? -1 : 1;
+                return local.plusHours(plusHr * mul).toInstant().toEpochMilli();
             }
-
-            return c.getTimeInMillis();
+            return local.toInstant().toEpochMilli();
         } else if (checkLayout(str, "xxxx-xx-xxTxx:xx:xx.xxxZ") ||
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx.xxx") ||
@@ -124,20 +107,21 @@
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx.xxx+xx:00") ||
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx.xxx-xx:00")) {
-            // consider EXIF date in default timezone
-            final Calendar c = checkLayout(str, "xxxx:xx:xx xx:xx:xx.xxx") ? getLocalCalendar() : calendar;
-            c.set(
+            final ZonedDateTime local = ZonedDateTime.of(
                 parsePart4(str, 0),
-                parsePart2(str, 5)-1,
+                parsePart2(str, 5),
                 parsePart2(str, 8),
                 parsePart2(str, 11),
                 parsePart2(str, 14),
-                parsePart2(str, 17));
-            c.set(Calendar.MILLISECOND, 0);
-            long millis = parsePart3(str, 20);
+                parsePart2(str, 17),
+                parsePart3(str, 20) * 1_000_000,
+                // consider EXIF date in default timezone
+                checkLayout(str, "xxxx:xx:xx xx:xx:xx.xxx") ? ZoneId.systemDefault() : ZoneOffset.UTC
+            );
             if (str.length() == 29) {
-                millis += parsePart2(str, 24) * (str.charAt(23) == '+' ? -3600000 : 3600000);
+                final int plusHr = parsePart2(str, 24);
+                final int mul = str.charAt(23) == '+' ? -1 : 1;
+                return local.plusHours(plusHr * mul).toInstant().toEpochMilli();
             }
-
-            return c.getTimeInMillis() + millis;
+            return local.toInstant().toEpochMilli();
         } else {
             // example date format "18-AUG-08 13:33:03"
@@ -155,18 +139,4 @@
     }
 
-    private static Calendar getLocalCalendar() {
-        final Calendar c = calendarLocale;
-        c.setTimeZone(TimeZone.getDefault());
-        return c;
-    }
-
-    private static String toXmlFormat(GregorianCalendar cal) {
-        XMLGregorianCalendar xgc = XML_DATE.newXMLGregorianCalendar(cal);
-        if (cal.get(Calendar.MILLISECOND) == 0) {
-            xgc.setFractionalSecond(null);
-        }
-        return xgc.toXMLFormat();
-    }
-
     /**
      * Formats a date to the XML UTC format regardless of current locale.
@@ -175,6 +145,6 @@
      */
     public static synchronized String fromTimestamp(int timestamp) {
-        calendar.setTimeInMillis(timestamp * 1000L);
-        return toXmlFormat(calendar);
+        final ZonedDateTime temporal = Instant.ofEpochMilli(timestamp * 1000L).atZone(ZoneOffset.UTC);
+        return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(temporal);
     }
 
@@ -185,6 +155,6 @@
      */
     public static synchronized String fromDate(Date date) {
-        calendar.setTime(date);
-        return toXmlFormat(calendar);
+        final ZonedDateTime temporal = date.toInstant().atZone(ZoneOffset.UTC);
+        return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(temporal);
     }
 
