Index: src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 1481)
+++ src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(working copy)
@@ -16,6 +16,7 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.tools.DateUtils;
 
 /**
  * Implements a google-like search.
@@ -145,7 +146,7 @@
                 String value = null;
 
                 if (key.equals("timestamp"))
-                    value = osm.getTimeStr();
+                    value = DateUtils.fromDate(osm.getTimestamp());
                 else
                     value = osm.get(key);
 
Index: src/org/openstreetmap/josm/tools/DateUtils.java
===================================================================
--- src/org/openstreetmap/josm/tools/DateUtils.java	(revision 0)
+++ src/org/openstreetmap/josm/tools/DateUtils.java	(revision 0)
@@ -0,0 +1,111 @@
+/*
+ *  JOSMng - a Java Open Street Map editor, the next generation.
+ * 
+ *  Copyright (C) 2008 Petr Nejedly <P.Nejedly@sh.cvut.cz>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+package org.openstreetmap.josm.tools;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+
+/**
+ * A static utility class dealing with parsing XML date quickly and formatting
+ * a date to the XML UTC format regardless of current locale.
+ * 
+ * @author nenik
+ */
+public final class DateUtils {
+    private DateUtils() {}
+    /**
+     * 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 GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+    private static final DatatypeFactory XML_DATE;
+
+    static {
+        calendar.setTimeInMillis(0);
+        
+        DatatypeFactory fact = null;
+        try {
+            fact = DatatypeFactory.newInstance();
+        } catch(DatatypeConfigurationException ce) {
+            ce.printStackTrace();
+        }
+        XML_DATE = fact;
+    }
+
+    public static synchronized Date fromString(String str) {
+        // "2007-07-25T09:26:24{Z|{+|-}01:00}"
+        if (checkLayout(str, "xxxx-xx-xxTxx:xx:xxZ") ||
+                checkLayout(str, "xxxx-xx-xxTxx:xx:xx+xx:00") ||
+                checkLayout(str, "xxxx-xx-xxTxx:xx:xx-xx:00")) {
+            calendar.set(
+                parsePart(str, 0, 4),
+                parsePart(str, 5, 2)-1,
+                parsePart(str, 8, 2),
+                parsePart(str, 11, 2),
+                parsePart(str, 14,2),
+                parsePart(str, 17, 2));
+
+            if (str.length() == 25) {
+                int plusHr = parsePart(str, 20, 2);
+                int mul = str.charAt(19) == '+' ? -3600000 : 3600000;
+                calendar.setTimeInMillis(calendar.getTimeInMillis()+plusHr*mul);
+            }
+
+            return calendar.getTime();
+        }
+
+        try {
+            return XML_DATE.newXMLGregorianCalendar(str).toGregorianCalendar().getTime();
+        } catch (Exception ex) {
+            return new Date();
+        }
+    }
+    
+    public static synchronized String fromDate(Date date) {
+        calendar.setTime(date);
+        XMLGregorianCalendar xgc = XML_DATE.newXMLGregorianCalendar(calendar);
+        if (calendar.get(Calendar.MILLISECOND) == 0) xgc.setFractionalSecond(null);
+        return xgc.toXMLFormat();
+    }
+        
+    private static boolean checkLayout(String text, String pattern) {
+        if (text.length() != pattern.length()) return false;
+        for (int i=0; i<pattern.length(); i++) {
+            if (pattern.charAt(i) == 'x') continue;
+            if (pattern.charAt(i) != text.charAt(i)) return false;
+        }
+        return true;
+    }
+
+    private static int parsePart(String str, int off, int len) {
+        return Integer.valueOf(str.substring(off, off+len));
+    }
+
+}
Index: src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 1481)
+++ src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(working copy)
@@ -60,6 +60,7 @@
 import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+import org.openstreetmap.josm.tools.DateUtils;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -404,10 +405,10 @@
                 if (!n.tagged) {
                     doneNodes.add(n);
                 }
-                WayPoint wpt = new WayPoint(n.coor);
-                if (n.timestamp != null)
+                WayPoint wpt = new WayPoint(n.coor);                
+                if (!n.isTimestampEmpty())
                 {
-                    wpt.attr.put("time", n.timestamp);
+                    wpt.attr.put("time", DateUtils.fromDate(n.getTimestamp()));
                     wpt.setTime();
                 }
                 trkseg.add(wpt);
@@ -419,8 +420,8 @@
         for (Node n : data.nodes) {
             if (n.incomplete || n.deleted || doneNodes.contains(n)) continue;
             WayPoint wpt = new WayPoint(n.coor);
-            if (n.timestamp != null) {
-                wpt.attr.put("time", n.timestamp);
+            if (!n.isTimestampEmpty()) {
+                wpt.attr.put("time", DateUtils.fromDate(n.getTimestamp()));
                 wpt.setTime();
             }
             if (n.keys != null && n.keys.containsKey("name")) {
Index: src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 1481)
+++ src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(working copy)
@@ -67,6 +67,7 @@
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker;
 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
+import org.openstreetmap.josm.tools.DateUtils;
 import org.openstreetmap.josm.tools.DontShowAgainInfo;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -659,8 +660,7 @@
                         String timestr = p.getString("time");
                         if(timestr != null)
                         {
-                            timestr = timestr.replace("Z","+00:00");
-                            n.timestamp = timestr;
+                            n.setTimestamp(DateUtils.fromString(timestr));
                         }
                         ds.nodes.add(n);
                         w.nodes.add(n);
Index: src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 1481)
+++ src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(working copy)
@@ -35,6 +35,7 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.SideButton;
+import org.openstreetmap.josm.tools.DateUtils;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -170,7 +171,7 @@
                 orderedHistory.addAll(cache.get(osm));
             data.setRowCount(0);
             for (HistoryItem i : orderedHistory)
-                data.addRow(new Object[]{i.osm, i.osm.timestamp, i.visible});
+                data.addRow(new Object[]{i.osm, DateUtils.fromDate(i.osm.getTimestamp()), i.visible});
             historyPane.setVisible(true);
             notLoaded.setVisible(false);
         }
Index: src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmReader.java	(revision 1481)
+++ src/org/openstreetmap/josm/io/OsmReader.java	(working copy)
@@ -32,6 +32,7 @@
 import org.openstreetmap.josm.data.osm.visitor.AddVisitor;
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.gui.PleaseWaitDialog;
+import org.openstreetmap.josm.tools.DateUtils;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -100,7 +101,7 @@
                osm.modified = modified;
                osm.selected = selected;
                osm.deleted = deleted;
-               osm.timestamp = timestamp;
+               osm.setTimestamp(getTimestamp());
                osm.user = user;
                osm.visible = visible;
                osm.version = version;
@@ -296,16 +297,7 @@
 
           String time = atts.getValue("timestamp");
           if (time != null && time.length() != 0) {
-               /* Do not parse the date here since it wastes a HUGE amount of time.
-                * Moved into OsmPrimitive.
-               try {
-                    current.timestamp = DateParser.parse(time);
-               } catch (ParseException e) {
-                    e.printStackTrace();
-                    throw new SAXException(tr("Couldn''t read time format \"{0}\".",time));
-               }
-               */
-               current.timestamp = time;
+               current.setTimestamp(DateUtils.fromString(time));
           }
 
           // user attribute added in 0.4 API
Index: src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmWriter.java	(revision 1481)
+++ src/org/openstreetmap/josm/io/OsmWriter.java	(working copy)
@@ -15,6 +15,7 @@
 import org.openstreetmap.josm.data.osm.Changeset;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
+import org.openstreetmap.josm.tools.DateUtils;
 
 /**
  * Save the dataset into a stream as osm intern xml format. This is not using any
@@ -200,8 +201,8 @@
             if (action != null)
                 out.print(" action='"+action+"'");
         }
-        if (osm.timestamp != null) {
-            out.print(" timestamp='"+osm.timestamp+"'");
+        if (!osm.isTimestampEmpty()) {
+            out.print(" timestamp='"+DateUtils.fromDate(osm.getTimestamp())+"'");
         }
         // user and visible added with 0.4 API
         if (osm.user != null) {
Index: src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(revision 1481)
+++ src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java	(working copy)
@@ -234,20 +234,20 @@
                 return true; // no merge needed.
             }
             if (my.realEqual(other, true)) {
-                Date myd = my.timestamp == null ? new Date(0) : my.getTimestamp();
-                Date otherd = other.timestamp == null ? new Date(0) : other.getTimestamp();
+                Date myd = my.getTimestamp();
+                Date otherd = other.getTimestamp();
 
                 // they differ in modified/timestamp combination only. Auto-resolve it.
                 merged.put(other, my);
                 if (myd.before(otherd)) {
                     my.modified = other.modified;
-                    my.timestamp = other.timestamp;
+                    my.setTimestamp(other.getTimestamp());
                 }
                 return true; // merge done.
             }
             if (my.id == other.id && my.id != 0) {
-                Date myd = my.timestamp == null ? new Date(0) : my.getTimestamp();
-                Date otherd = other.timestamp == null ? new Date(0) : other.getTimestamp();
+                Date myd = my.getTimestamp();
+                Date otherd = other.getTimestamp();
 
                 if (my.incomplete || other.incomplete) {
                     if (my.incomplete) {
Index: src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 1481)
+++ src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(working copy)
@@ -3,21 +3,17 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.openstreetmap.josm.data.osm.visitor.Visitor;
-import org.openstreetmap.josm.tools.DateParser;
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.gui.mappaint.ElemStyle;
 
 
@@ -129,20 +125,27 @@
      */
     public volatile boolean highlighted = false;
 
+    private int timestamp;
+    
+    public void setTimestamp(Date timestamp) {
+        this.timestamp = (int)(timestamp.getTime() / 1000);
+    }
+    
     /**
      * Time of last modification to this object. This is not set by JOSM but
      * read from the server and delivered back to the server unmodified. It is
      * used to check against edit conflicts.
-     */
-    public String timestamp = null;
+     * 
+     */    
+    public Date getTimestamp() {
+        return new Date(timestamp * 1000l);
+    }
+    
+    public boolean isTimestampEmpty() {
+        return timestamp == 0;
+    }
 
     /**
-     * The timestamp is only parsed when this is really necessary, and this
-     * is the cache for the result.
-     */
-    public Date parsedTimestamp = null;
-
-    /**
      * If set to true, this object is incomplete, which means only the id
      * and type is known (type is the objects instance class)
      */
@@ -182,22 +185,6 @@
     }
 
     /**
-     * Returns the timestamp for this object, or the current time if none is set.
-     * Internally, parses the timestamp from XML into a Date object and caches it
-     * for possible repeated calls.
-     */
-    public Date getTimestamp() {
-        if (parsedTimestamp == null) {
-            try {
-                parsedTimestamp = DateParser.parse(timestamp);
-            } catch (ParseException ex) {
-                parsedTimestamp = new Date();
-            }
-        }
-        return parsedTimestamp;
-    }
-
-    /**
      * Equal, if the id (and class) is equal.
      *
      * An primitive is equal to its incomplete counter part.
@@ -308,17 +295,13 @@
             incomplete == osm.incomplete &&
             (semanticOnly || (modified == osm.modified)) &&
             deleted == osm.deleted &&
-            (semanticOnly || (timestamp == null ? osm.timestamp==null : timestamp.equals(osm.timestamp))) &&
+            (semanticOnly || timestamp == osm.timestamp) &&
             (semanticOnly || (version==osm.version)) &&
             (semanticOnly || (user == null ? osm.user==null : user==osm.user)) &&
             (semanticOnly || (visible == osm.visible)) &&
             (keys == null ? osm.keys==null : keys.equals(osm.keys));
     }
 
-    public String getTimeStr() {
-        return timestamp == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp);
-    }
-
     /**
      * Updates the "tagged" flag. "keys" property should probably be made private
      * to make sure this gets called when keys are set.
