Index: src/org/openstreetmap/josm/data/gpx/GpxData.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 14455)
+++ src/org/openstreetmap/josm/data/gpx/GpxData.java	(working copy)
@@ -8,11 +8,11 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
-import java.util.DoubleSummaryStatistics;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.LongSummaryStatistics;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
@@ -174,7 +174,7 @@
                 WayPoint prevLastOwnWp = null;
                 Date prevWpTime = null;
                 for (WayPoint wp : wpsOld) {
-                    Date wpTime = wp.setTimeFromAttribute();
+                    Date wpTime = wp.getDate();
                     boolean overlap = false;
                     if (wpTime != null) {
                         for (GpxTrackSegmentSpan ownspan : getSegmentSpans()) {
@@ -266,8 +266,8 @@
         private final WayPoint lastWp;
 
         GpxTrackSegmentSpan(WayPoint a, WayPoint b) {
-            Date at = a.getTime();
-            Date bt = b.getTime();
+            Date at = a.getDate();
+            Date bt = b.getDate();
             inv = bt.before(at);
             if (inv) {
                 firstWp = b;
@@ -323,7 +323,7 @@
         private static WayPoint getNextWpWithTime(GpxTrackSegment seg, boolean forward) {
             List<WayPoint> wps = new ArrayList<>(seg.getWayPoints());
             for (int i = forward ? 0 : wps.size() - 1; i >= 0 && i < wps.size(); i += forward ? 1 : -1) {
-                if (wps.get(i).setTimeFromAttribute() != null) {
+                if (wps.get(i).hasDate()) {
                     return wps.get(i);
                 }
             }
@@ -690,13 +690,13 @@
      * @return  minimum and maximum dates in array of 2 elements
      */
     public static Date[] getMinMaxTimeForTrack(GpxTrack trk) {
-        final DoubleSummaryStatistics statistics = trk.getSegments().stream()
+        final LongSummaryStatistics statistics = trk.getSegments().stream()
                 .flatMap(seg -> seg.getWayPoints().stream())
-                .mapToDouble(pnt -> pnt.time)
+                .mapToLong(pnt -> pnt.getTimeInMillis())
                 .summaryStatistics();
         return statistics.getCount() == 0
                 ? null
-                : new Date[]{new Date((long) (statistics.getMin() * 1000)), new Date((long) (statistics.getMax() * 1000))};
+                : new Date[]{new Date(statistics.getMin()), new Date(statistics.getMax())};
     }
 
     /**
@@ -707,16 +707,16 @@
      * @return minimum and maximum dates in array of 2 elements
     */
     public synchronized Date[] getMinMaxTimeForAllTracks() {
-        double now = System.currentTimeMillis() / 1000.0;
-        final DoubleSummaryStatistics statistics = tracks.stream()
+        long now = System.currentTimeMillis();
+        final LongSummaryStatistics statistics = tracks.stream()
                 .flatMap(trk -> trk.getSegments().stream())
                 .flatMap(seg -> seg.getWayPoints().stream())
-                .mapToDouble(pnt -> pnt.time)
+                .mapToLong(pnt -> pnt.getTimeInMillis())
                 .filter(t -> t > 0 && t <= now)
                 .summaryStatistics();
         return statistics.getCount() == 0
                 ? new Date[0]
-                : new Date[]{new Date((long) (statistics.getMin() * 1000)), new Date((long) (statistics.getMax() * 1000))};
+                : new Date[]{new Date(statistics.getMin()), new Date(statistics.getMax())};
     }
 
     /**
@@ -754,7 +754,7 @@
 
         double pnminsq = tolerance * tolerance;
         EastNorth bestEN = null;
-        double bestTime = 0.0;
+        Double bestTime = null;
         double px = p.east();
         double py = p.north();
         double rx = 0.0, ry = 0.0, sx, sy, x, y;
@@ -773,7 +773,9 @@
                         if (pRsq < pnminsq) {
                             pnminsq = pRsq;
                             bestEN = en;
-                            bestTime = r.time;
+                            if (r.hasDate()) {
+                                bestTime = r.getTime();
+                            }
                         }
                     } else {
                         sx = en.east();
@@ -799,7 +801,9 @@
                                 double nx = rx - rnoverRS * b;
                                 double ny = ry + rnoverRS * a;
                                 bestEN = new EastNorth(nx, ny);
-                                bestTime = r.time + rnoverRS * (wpSeg.time - r.time);
+                                if (r.hasDate() && wpSeg.hasDate()) {
+                                    bestTime = r.getTime() + rnoverRS * (wpSeg.getTime() - r.getTime());
+                                }
                                 pnminsq = pnsq;
                             }
                         }
@@ -819,7 +823,9 @@
                     if (prsq < pnminsq) {
                         pnminsq = prsq;
                         bestEN = c;
-                        bestTime = r.time;
+                        if (r.hasDate()) {
+                            bestTime = r.getTime();
+                        }
                     }
                 }
             }
@@ -827,7 +833,9 @@
         if (bestEN == null)
             return null;
         WayPoint best = new WayPoint(ProjectionRegistry.getProjection().eastNorth2latlon(bestEN));
-        best.time = bestTime;
+        if (bestTime != null) {
+            best.setTimeInMillis((long) (bestTime * 1000));
+        }
         return best;
     }
 
Index: src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java	(revision 14455)
+++ src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java	(working copy)
@@ -45,7 +45,7 @@
                     //remove waypoints at the beginning of the track/segment without timestamps
                     int wp;
                     for (wp = 0; wp < wps.size(); wp++) {
-                        if (wps.get(wp).setTimeFromAttribute() != null) {
+                        if (wps.get(wp).hasDate()) {
                             break;
                         }
                     }
@@ -61,7 +61,7 @@
                 segs.sort((o1, o2) -> {
                     if (o1.isEmpty() || o2.isEmpty())
                         return 0;
-                    return Double.compare(o1.get(0).time, o2.get(0).time);
+                    return o1.get(0).compareTo(o2.get(0));
                 });
                 trks.add(segs);
             }
@@ -71,7 +71,7 @@
             if (o1.isEmpty() || o1.get(0).isEmpty()
              || o2.isEmpty() || o2.get(0).isEmpty())
                 return 0;
-            return Double.compare(o1.get(0).get(0).time, o2.get(0).get(0).time);
+            return o1.get(0).get(0).compareTo(o2.get(0).get(0));
         });
 
         boolean trkInt, trkTag, segInt, segTag;
@@ -110,29 +110,26 @@
                 List<WayPoint> wps = segs.get(s);
                 for (int i = 0; i < wps.size(); i++) {
                     WayPoint curWp = wps.get(i);
-                    Date parsedTime = curWp.setTimeFromAttribute();
                     // Interpolate timestamps in the segment, if one or more waypoints miss them
-                    if (parsedTime == null) {
+                    if (!curWp.hasDate()) {
                         //check if any of the following waypoints has a timestamp...
-                        if (i > 0 && wps.get(i - 1).time != 0) {
-                            long prevWpTimeNoOffset = wps.get(i - 1).getTime().getTime();
+                        if (i > 0 && wps.get(i - 1).hasDate()) {
+                            long prevWpTimeNoOffset = wps.get(i - 1).getTimeInMillis();
                             double totalDist = 0;
                             List<Pair<Double, WayPoint>> nextWps = new ArrayList<>();
                             for (int j = i; j < wps.size(); j++) {
                                 totalDist += wps.get(j - 1).getCoor().greatCircleDistance(wps.get(j).getCoor());
                                 nextWps.add(new Pair<>(totalDist, wps.get(j)));
-                                final Date nextTime = wps.get(j).setTimeFromAttribute();
-                                if (nextTime != null) {
+                                if (wps.get(j).hasDate()) {
                                     // ...if yes, interpolate everything in between
-                                    long timeDiff = nextTime.getTime() - prevWpTimeNoOffset;
+                                    long timeDiff = wps.get(j).getTimeInMillis() - prevWpTimeNoOffset;
                                     for (Pair<Double, WayPoint> pair : nextWps) {
-                                        pair.b.setTime(new Date((long) (prevWpTimeNoOffset + (timeDiff * (pair.a / totalDist)))));
+                                        pair.b.setTimeInMillis((long) (prevWpTimeNoOffset + (timeDiff * (pair.a / totalDist))));
                                     }
                                     break;
                                 }
                             }
-                            parsedTime = curWp.setTimeFromAttribute();
-                            if (parsedTime == null) {
+                            if (!curWp.hasDate()) {
                                 break; //It's pointless to continue with this segment, because none of the following waypoints had a timestamp
                             }
                         } else {
@@ -141,7 +138,7 @@
                         }
                     }
 
-                    final long curWpTime = parsedTime.getTime() + offset;
+                    final long curWpTime = curWp.getTimeInMillis() + offset;
                     boolean interpolate = true;
                     int tagTime = 0;
                     if (i == 0) {
Index: src/org/openstreetmap/josm/data/gpx/WayPoint.java
===================================================================
--- src/org/openstreetmap/josm/data/gpx/WayPoint.java	(revision 14455)
+++ src/org/openstreetmap/josm/data/gpx/WayPoint.java	(working copy)
@@ -4,6 +4,7 @@
 import java.awt.Color;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Objects;
 
@@ -13,6 +14,7 @@
 import org.openstreetmap.josm.data.osm.search.SearchCompiler.Match;
 import org.openstreetmap.josm.data.projection.Projecting;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.date.DateUtils;
 import org.openstreetmap.josm.tools.template_engine.TemplateEngineDataProvider;
 
 /**
@@ -22,35 +24,53 @@
 public class WayPoint extends WithAttributes implements Comparable<WayPoint>, TemplateEngineDataProvider, ILatLon {
 
     /**
-     * The seconds (not milliseconds!) since 1970-01-01 00:00 UTC
-     */
-    public double time;
-    /**
      * The color to draw the segment before this point in
      * @see #drawLine
      */
     public Color customColoring;
+
     /**
      * <code>true</code> indicates that the line before this point should be drawn
      */
     public boolean drawLine;
+
     /**
      * The direction of the line before this point. Used as cache to speed up drawing. Should not be relied on.
      */
     public int dir;
 
+    /*
+     * We "inline" lat/lon, rather than usinga LatLon internally => reduces memory overhead. Relevant
+     * because a lot of GPX waypoints are created when GPS tracks are downloaded from the OSM server.
+     */
+    private final double lat;
+    private final double lon;
+
+    /*
+     * internal cache of projected coordinates
+     */
+    private double east = Double.NaN;
+    private double north = Double.NaN;
+    private Object eastNorthCacheKey;
+
     /**
      * Constructs a new {@code WayPoint} from an existing one.
+     *
+     * Except for PT_TIME attribute, all attribute objects are
+     * shallow copied.  This means modification of attr objects
+     * will affect original and new {@code WayPoint}.
+     *
      * @param p existing waypoint
      */
     public WayPoint(WayPoint p) {
+        init_attr();
         attr.putAll(p.attr);
+        attr.put(PT_TIME, p.getDate());
         lat = p.lat;
         lon = p.lon;
         east = p.east;
         north = p.north;
         eastNorthCacheKey = p.eastNorthCacheKey;
-        time = p.time;
         customColoring = p.customColoring;
         drawLine = p.drawLine;
         dir = p.dir;
@@ -61,23 +81,39 @@
      * @param ll lat/lon coordinates
      */
     public WayPoint(LatLon ll) {
+        init_attr();
         lat = ll.lat();
         lon = ll.lon();
     }
 
-    /*
-     * We "inline" lat/lon, rather than usinga LatLon internally => reduces memory overhead. Relevant
-     * because a lot of GPX waypoints are created when GPS tracks are downloaded from the OSM server.
-     */
-    private final double lat;
-    private final double lon;
-
-    /*
-     * internal cache of projected coordinates
+    /**
+     * Interim to detect legacy code that is not using {@code WayPoint.setTime(x)}
+     * functions, but {@code attr.put(PT_TIME, (String) x)} logic.
      */
-    private double east = Double.NaN;
-    private double north = Double.NaN;
-    private Object eastNorthCacheKey;
+    private void init_attr() {
+        attr = new HashMap<String, Object>(0) {
+            @Override
+            public Object put(String key, Object value) {
+                Object ret = null;
+                if (key != PT_TIME || (key == PT_TIME && value instanceof Date)) {
+                    ret = super.put(key, value);
+                } else {
+                    if (value instanceof String) {
+                        ret = super.put(PT_TIME, DateUtils.fromString((String) value));
+                        if (!Logging.getLastErrorAndWarnings().get(0).contains("calling WayPoint.put")) {
+                            StackTraceElement[] e = Thread.currentThread().getStackTrace();
+                            int n = 1;
+                            while (n < e.length && e[n].getMethodName().equals("put"))
+                                n++;
+                            Logging.warn("{0}:{1} calling WayPoint.put(PT_TIME, ..) is deprecated. " +
+                                "Use WayPoint.setTime(..) instead.", e[n].getClassName(), e[n].getMethodName());
+                        }
+                    }
+                }
+                return ret;
+            }
+        };
+    }
 
     /**
      * Invalidate the internal cache of east/north coordinates.
@@ -125,80 +161,100 @@
     }
 
     /**
-     * Sets the {@link #time} field as well as the {@link #PT_TIME} attribute to the specified time.
+     * Sets the {@link #PT_TIME} attribute to the specified time.
      *
-     * @param time the time to set
+     * @param date the time to set
      * @since 9383
      */
-    public void setTime(Date time) {
-        this.time = time.getTime() / 1000.;
-        this.attr.put(PT_TIME, time);
+    public void setTime(Date date) {
+        setTimeInMillis(date.getTime());
     }
 
     /**
-     * Convert the time stamp of the waypoint into seconds from the epoch.
-     *
-     * @deprecated call {@link #setTimeFromAttribute()} directly if you need this
-     */
-    @Deprecated
-    public void setTime() {
-        setTimeFromAttribute();
-    }
-
-    /**
-     * Sets the {@link #time} field as well as the {@link #PT_TIME} attribute to the specified time.
+     * Sets the {@link #PT_TIME} attribute to the specified time.
      *
      * @param ts seconds from the epoch
      * @since 13210
      */
     public void setTime(long ts) {
-        setTimeInMillis(ts*1000);
+        setTimeInMillis(ts * 1000);
     }
 
     /**
-     * Sets the {@link #time} field as well as the {@link #PT_TIME} attribute to the specified time.
+     * Sets the {@link #PT_TIME} attribute to the specified time.
      *
      * @param ts milliseconds from the epoch
      * @since 14434
      */
     public void setTimeInMillis(long ts) {
-        this.time = ts / 1000.;
-        this.attr.put(PT_TIME, new Date(ts));
+        attr.put(PT_TIME, new Date(ts));
+    }
+
+    @Override
+    public int compareTo(WayPoint other) {
+        return Long.compare(getTimeInMillis(), other.getTimeInMillis());
     }
 
     /**
-     * Convert the time stamp of the waypoint into seconds from the epoch
-     * @return The parsed time if successful, or {@code null}
-     * @since 9383
+     * Returns the waypoint time in seconds since the epoch.
+     *
+     * @return the waypoint time
      */
-    public Date setTimeFromAttribute() {
-        if (attr.containsKey(PT_TIME)) {
-            final Object obj = get(PT_TIME);
+    public double getTime() {
+        return getTimeInMillis() / 1000.;
+    }
+
+    /**
+     * Returns the waypoint time in milliseconds since the epoch.
+     *
+     * @return the waypoint time
+     */
+    public long getTimeInMillis() {
+        Date d = getDateImpl();
+        return d == null ? 0 : d.getTime();
+    }
+
+    /**
+     * Returns true if this waypoint has a time.
+     *
+     * @return true if a time is set, false otherwise
+     */
+    public boolean hasDate() {
+        return attr.get(PT_TIME) instanceof Date;
+    }
+
+    /**
+     * Returns the waypoint time Date object.
+     *
+     * @return a copy of the Date object associated with this waypoint
+     */
+    public Date getDate() {
+        return DateUtils.cloneDate(getDateImpl());
+    }
+
+    /**
+     * Returns the waypoint time Date object.
+     *
+     * @return the Date object associated with this waypoint
+     */
+    private Date getDateImpl() {
+        Date ret = null;
+
+        try {
+            final Object obj = attr.get(PT_TIME);
+
             if (obj instanceof Date) {
-                final Date date = (Date) obj;
-                time = date.getTime() / 1000.;
-                return date;
+                ret = (Date) obj;
             } else if (obj == null) {
                 Logging.info("Waypoint {0} value unset", PT_TIME);
             } else {
                 Logging.warn("Unsupported waypoint {0} value: {1}", PT_TIME, obj);
-                time = 0;
             }
+        } catch (NullPointerException e) {
+            // satisfies WayPointTest.testEqualsContract()
         }
-        return null;
-    }
 
-    @Override
-    public int compareTo(WayPoint w) {
-        return Double.compare(time, w.time);
-    }
-
-    /**
-     * Returns the waypoint time.
-     * @return the waypoint time
-     */
-    public Date getTime() {
-        return new Date((long) (time * 1000));
+        return ret;
     }
 
     @Override
@@ -227,7 +283,7 @@
         result = prime * result + (int) (temp ^ (temp >>> 32));
         temp = Double.doubleToLongBits(lon);
         result = prime * result + (int) (temp ^ (temp >>> 32));
-        temp = Double.doubleToLongBits(time);
+        temp = getTimeInMillis();
         result = prime * result + (int) (temp ^ (temp >>> 32));
         return result;
     }
@@ -241,6 +297,29 @@
         WayPoint other = (WayPoint) obj;
         return Double.doubleToLongBits(lat) == Double.doubleToLongBits(other.lat)
             && Double.doubleToLongBits(lon) == Double.doubleToLongBits(other.lon)
-            && Double.doubleToLongBits(time) == Double.doubleToLongBits(other.time);
+            && getTimeInMillis() == other.getTimeInMillis();
+    }
+
+    /**
+     * Convert the time stamp of the waypoint into seconds from the epoch.
+     *
+     * @deprecated
+     */
+    @Deprecated
+    public void setTime() {
+        setTimeFromAttribute();
+    }
+
+    /**
+     * Convert the time stamp of the waypoint into seconds from the epoch.
+     * @return The parsed time if successful, or {@code null}
+     * @since 9383
+     *
+     * @deprecated
+     */
+    @Deprecated
+    public Date setTimeFromAttribute() {
+        Logging.warn("WayPoint.setTimeFromAttribute() is deprecated, please fix calling code");
+        return getDate();
     }
 }
Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 14455)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(working copy)
@@ -800,7 +800,7 @@
             if (time > Long.MIN_VALUE) {
                 wpt.setTimeInMillis(time);
             } else if (n.hasKey(GpxConstants.PT_TIME)) {
-                wpt.setTime(DateUtils.fromString(n.get(GpxConstants.PT_TIME)));
+                wpt.setTimeInMillis(DateUtils.tsFromString(n.get(GpxConstants.PT_TIME)));
             } else if (!n.isTimestampEmpty()) {
                 wpt.setTime(Integer.toUnsignedLong(n.getRawTimestamp()));
             }
Index: src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(revision 14455)
+++ src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java	(working copy)
@@ -1229,9 +1229,8 @@
         outer: for (GpxTrack trk : gpx.tracks) {
             for (GpxTrackSegment segment : trk.getSegments()) {
                 for (WayPoint curWp : segment.getWayPoints()) {
-                    final Date parsedTime = curWp.setTimeFromAttribute();
-                    if (parsedTime != null) {
-                        firstGPXDate = parsedTime.getTime();
+                    if (curWp.hasDate()) {
+                        firstGPXDate = curWp.getTimeInMillis();
                         break outer;
                     }
                 }
Index: src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java	(revision 14455)
+++ src/org/openstreetmap/josm/gui/layer/gpx/GpxDrawHelper.java	(working copy)
@@ -508,9 +508,9 @@
                         if (!trkPnt.isLatLonKnown()) {
                             continue;
                         }
-                        if (oldWp != null && trkPnt.time > oldWp.time) {
+                        if (oldWp != null && trkPnt.getTimeInMillis() > oldWp.getTimeInMillis()) {
                             double vel = trkPnt.getCoor().greatCircleDistance(oldWp.getCoor())
-                                    / (trkPnt.time - oldWp.time);
+                                    / (trkPnt.getTime() - oldWp.getTime());
                             velocities.add(vel);
                         }
                         oldWp = trkPnt;
@@ -586,7 +586,7 @@
                     boolean noDraw = false;
                     switch (colored) {
                     case VELOCITY:
-                        double dtime = trkPnt.time - oldWp.time;
+                        double dtime = trkPnt.getTime() - oldWp.getTime();
                         if (dtime > 0) {
                             color = velocityScale.getColor(dist / dtime);
                         } else {
@@ -598,7 +598,7 @@
                         color = directionScale.getColor(dirColor);
                         break;
                     case TIME:
-                        double t = trkPnt.time;
+                        double t = trkPnt.getTime();
                         // skip bad timestamps and very short tracks
                         if (t > 0 && t <= now && maxval - minval > minTrackDurationForTimeColoring) {
                             color = dateScale.getColor(t);
Index: src/org/openstreetmap/josm/gui/layer/gpx/ImportAudioAction.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/gpx/ImportAudioAction.java	(revision 14455)
+++ src/org/openstreetmap/josm/gui/layer/gpx/ImportAudioAction.java	(working copy)
@@ -149,7 +149,7 @@
             for (GpxTrack track : layer.data.tracks) {
                 for (GpxTrackSegment seg : track.getSegments()) {
                     for (WayPoint w : seg.getWayPoints()) {
-                        firstTime = w.time;
+                        firstTime = w.getTime();
                         break;
                     }
                     if (firstTime >= 0.0) {
@@ -174,9 +174,9 @@
         // (a) try explicit timestamped waypoints - unless suppressed
         if (hasWaypoints && Config.getPref().getBoolean("marker.audiofromexplicitwaypoints", true)) {
             for (WayPoint w : layer.data.waypoints) {
-                if (w.time > firstTime) {
+                if (w.getTime() > firstTime) {
                     waypoints.add(w);
-                } else if (w.time > 0.0) {
+                } else if (w.getTime() > 0.0) {
                     timedMarkersOmitted = true;
                 }
             }
@@ -191,7 +191,7 @@
                 WayPoint wNear = layer.data.nearestPointOnTrack(w.getEastNorth(ProjectionRegistry.getProjection()), snapDistance);
                 if (wNear != null) {
                     WayPoint wc = new WayPoint(w.getCoor());
-                    wc.time = wNear.time;
+                    wc.setTimeInMillis(wNear.getTimeInMillis());
                     if (w.attr.containsKey(GpxConstants.GPX_NAME)) {
                         wc.put(GpxConstants.GPX_NAME, w.getString(GpxConstants.GPX_NAME));
                     }
@@ -229,7 +229,7 @@
             for (GpxTrack track : layer.data.tracks) {
                 for (GpxTrackSegment seg : track.getSegments()) {
                     for (WayPoint w : seg.getWayPoints()) {
-                        if (startTime < w.time) {
+                        if (startTime < w.getTime()) {
                             w2 = w;
                             break;
                         }
@@ -245,8 +245,8 @@
                 timedMarkersOmitted = true;
             } else {
                 wayPointFromTimeStamp = new WayPoint(w1.getCoor().interpolate(w2.getCoor(),
-                        (startTime - w1.time) / (w2.time - w1.time)));
-                wayPointFromTimeStamp.time = startTime;
+                        (startTime - w1.getTime()) / (w2.getTime() - w1.getTime())));
+                wayPointFromTimeStamp.setTimeInMillis((long) (startTime * 1000));
                 String name = audioFile.getName();
                 int dot = name.lastIndexOf('.');
                 if (dot > 0) {
@@ -267,7 +267,7 @@
                     for (WayPoint w : seg.getWayPoints()) {
                         WayPoint wStart = new WayPoint(w.getCoor());
                         wStart.put(GpxConstants.GPX_NAME, "start");
-                        wStart.time = w.time;
+                        wStart.setTimeInMillis(w.getTimeInMillis());
                         waypoints.add(wStart);
                         gotOne = true;
                         break;
@@ -283,15 +283,15 @@
         }
 
         // we must have got at least one waypoint now
-        ((ArrayList<WayPoint>) waypoints).sort(Comparator.comparingDouble(o -> o.time));
+        ((ArrayList<WayPoint>) waypoints).sort((wp, other) -> wp.compareTo(other));
 
         firstTime = -1.0; // this time of the first waypoint, not first trackpoint
         for (WayPoint w : waypoints) {
             if (firstTime < 0.0) {
-                firstTime = w.time;
+                firstTime = w.getTime();
             }
-            double offset = w.time - firstTime;
-            AudioMarker am = new AudioMarker(w.getCoor(), w, url, ml, w.time, offset);
+            double offset = w.getTime() - firstTime;
+            AudioMarker am = new AudioMarker(w.getCoor(), w, url, ml, w.getTime(), offset);
             // timeFromAudio intended for future use to shift markers of this type on synchronization
             if (w == wayPointFromTimeStamp) {
                 am.timeFromAudio = true;
Index: src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java	(revision 14455)
+++ src/org/openstreetmap/josm/gui/layer/markerlayer/Marker.java	(working copy)
@@ -255,7 +255,7 @@
      */
     public WayPoint convertToWayPoint() {
         WayPoint wpt = new WayPoint(getCoor());
-        wpt.setTime((long) (time*1000));
+        wpt.setTimeInMillis((long) (time * 1000));
         if (text != null) {
             wpt.addExtension("text", text);
         } else if (dataProvider != null) {
Index: src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java	(revision 14455)
+++ src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java	(working copy)
@@ -96,7 +96,7 @@
 
         for (WayPoint wpt : indata.waypoints) {
             /* calculate time differences in waypoints */
-            double time = wpt.time;
+            double time = wpt.getTime();
             boolean wptHasLink = wpt.attr.containsKey(GpxConstants.META_LINKS);
             if (firstTime < 0 && wptHasLink) {
                 firstTime = time;
Index: src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java	(revision 14455)
+++ src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java	(working copy)
@@ -166,7 +166,7 @@
             for (Marker m : recent.parentLayer.data) {
                 if (m instanceof AudioMarker) {
                     AudioMarker a = (AudioMarker) m;
-                    if (a.time > cw.time) {
+                    if (a.time > cw.getTime()) {
                         break;
                     }
                     ca = a;
@@ -187,7 +187,7 @@
         } else {
             if (cw != null) {
                 setCoor(cw.getCoor());
-                ca.play(cw.time - ca.time);
+                ca.play(cw.getTime() - ca.time);
             }
             endDrag(false);
         }
@@ -244,7 +244,7 @@
                 endDrag(true);
                 return;
             }
-            ca = recent.parentLayer.addAudioMarker(cw.time, cw.getCoor());
+            ca = recent.parentLayer.addAudioMarker(cw.getTime(), cw.getCoor());
         }
 
         /* Actually do the synchronization */
@@ -329,7 +329,7 @@
         for (GpxTrack track : trackLayer.data.getTracks()) {
             for (GpxTrackSegment trackseg : track.getSegments()) {
                 for (WayPoint w: trackseg.getWayPoints()) {
-                    if (audioTime < w.time) {
+                    if (audioTime < w.getTime()) {
                         w2 = w;
                         break;
                     }
@@ -349,7 +349,7 @@
         setEastNorth(w2 == null ?
                 w1.getEastNorth(ProjectionRegistry.getProjection()) :
                     w1.getEastNorth(ProjectionRegistry.getProjection()).interpolate(w2.getEastNorth(ProjectionRegistry.getProjection()),
-                            (audioTime - w1.time)/(w2.time - w1.time)));
+                            (audioTime - w1.getTime())/(w2.getTime() - w1.getTime())));
         time = audioTime;
         MapView mapView = MainApplication.getMap().mapView;
         if (jumpToMarker) {
Index: src/org/openstreetmap/josm/io/GpxReader.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxReader.java	(revision 14455)
+++ src/org/openstreetmap/josm/io/GpxReader.java	(working copy)
@@ -444,9 +444,9 @@
                         currentWayPoint.put(localName, 0f);
                     }
                     break;
-                case GpxConstants.PT_TIME:
+                case PT_TIME:
                     try {
-                        currentWayPoint.setTime(DateUtils.fromString(accumulator.toString()));
+                        currentWayPoint.setTimeInMillis(DateUtils.tsFromString(accumulator.toString()));
                     } catch (UncheckedParseException e) {
                         Logging.error(e);
                     }
Index: src/org/openstreetmap/josm/io/nmea/NmeaReader.java
===================================================================
--- src/org/openstreetmap/josm/io/nmea/NmeaReader.java	(revision 14455)
+++ src/org/openstreetmap/josm/io/nmea/NmeaReader.java	(working copy)
@@ -524,7 +524,7 @@
             ps.pDate = currentDate;
             if (ps.pWp != currentwp) {
                 if (ps.pWp != null) {
-                    ps.pWp.setTimeFromAttribute();
+                    ps.pWp.getDate();
                 }
                 ps.pWp = currentwp;
                 ps.waypoints.add(currentwp);
Index: test/unit/org/openstreetmap/josm/io/nmea/NmeaReaderTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/io/nmea/NmeaReaderTest.java	(revision 14455)
+++ test/unit/org/openstreetmap/josm/io/nmea/NmeaReaderTest.java	(working copy)
@@ -69,11 +69,11 @@
         assertEquals(DateUtils.fromString("2016-01-25T05:05:09.200Z"), wayPoints.get(0).get(GpxConstants.PT_TIME));
         assertEquals(DateUtils.fromString("2016-01-25T05:05:09.400Z"), wayPoints.get(1).get(GpxConstants.PT_TIME));
         assertEquals(DateUtils.fromString("2016-01-25T05:05:09.600Z"), wayPoints.get(2).get(GpxConstants.PT_TIME));
-        assertEquals(wayPoints.get(0).getTime(), wayPoints.get(0).get(GpxConstants.PT_TIME));
+        assertEquals(wayPoints.get(0).getDate(), wayPoints.get(0).get(GpxConstants.PT_TIME));
 
-        assertEquals("2016-01-25T05:05:09.200Z", iso8601.format(wayPoints.get(0).getTime()));
-        assertEquals("2016-01-25T05:05:09.400Z", iso8601.format(wayPoints.get(1).getTime()));
-        assertEquals("2016-01-25T05:05:09.600Z", iso8601.format(wayPoints.get(2).getTime()));
+        assertEquals("2016-01-25T05:05:09.200Z", iso8601.format(wayPoints.get(0).getDate()));
+        assertEquals("2016-01-25T05:05:09.400Z", iso8601.format(wayPoints.get(1).getDate()));
+        assertEquals("2016-01-25T05:05:09.600Z", iso8601.format(wayPoints.get(2).getDate()));
 
         assertEquals(new LatLon(46.98807, -1.400525), wayPoints.get(0).getCoor());
         assertEquals("38.9", wayPoints.get(0).get(GpxConstants.PT_ELE));
@@ -170,7 +170,7 @@
     }
 
     private static Date readDate(String nmeaLine) throws IOException, SAXException {
-        return readWayPoint(nmeaLine).getTime();
+        return readWayPoint(nmeaLine).getDate();
     }
 
     private static double readSpeed(String nmeaLine) throws IOException, SAXException {
