Ticket #2302: timestamp.patch
File timestamp.patch, 16.5 KB (added by , 16 years ago) |
---|
-
src/org/openstreetmap/josm/actions/search/SearchCompiler.java
16 16 import org.openstreetmap.josm.data.osm.Relation; 17 17 import org.openstreetmap.josm.data.osm.User; 18 18 import org.openstreetmap.josm.data.osm.Way; 19 import org.openstreetmap.josm.tools.DateUtils; 19 20 20 21 /** 21 22 * Implements a google-like search. … … 145 146 String value = null; 146 147 147 148 if (key.equals("timestamp")) 148 value = osm.getTimeStr();149 value = DateUtils.fromDate(osm.getTimestamp()); 149 150 else 150 151 value = osm.get(key); 151 152 -
src/org/openstreetmap/josm/tools/DateUtils.java
1 /* 2 * JOSMng - a Java Open Street Map editor, the next generation. 3 * 4 * Copyright (C) 2008 Petr Nejedly <P.Nejedly@sh.cvut.cz> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 package org.openstreetmap.josm.tools; 22 23 import java.util.Calendar; 24 import java.util.Date; 25 import java.util.GregorianCalendar; 26 import java.util.TimeZone; 27 28 import javax.xml.datatype.DatatypeConfigurationException; 29 import javax.xml.datatype.DatatypeFactory; 30 import javax.xml.datatype.XMLGregorianCalendar; 31 32 33 /** 34 * A static utility class dealing with parsing XML date quickly and formatting 35 * a date to the XML UTC format regardless of current locale. 36 * 37 * @author nenik 38 */ 39 public final class DateUtils { 40 private DateUtils() {} 41 /** 42 * A shared instance used for conversion between individual date fields 43 * and long millis time. It is guarded against conflict by the class lock. 44 * The shared instance is used because the construction, together 45 * with the timezone lookup, is very expensive. 46 */ 47 private static GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 48 private static final DatatypeFactory XML_DATE; 49 50 static { 51 calendar.setTimeInMillis(0); 52 53 DatatypeFactory fact = null; 54 try { 55 fact = DatatypeFactory.newInstance(); 56 } catch(DatatypeConfigurationException ce) { 57 ce.printStackTrace(); 58 } 59 XML_DATE = fact; 60 } 61 62 public static synchronized Date fromString(String str) { 63 // "2007-07-25T09:26:24{Z|{+|-}01:00}" 64 if (checkLayout(str, "xxxx-xx-xxTxx:xx:xxZ") || 65 checkLayout(str, "xxxx-xx-xxTxx:xx:xx+xx:00") || 66 checkLayout(str, "xxxx-xx-xxTxx:xx:xx-xx:00")) { 67 calendar.set( 68 parsePart(str, 0, 4), 69 parsePart(str, 5, 2)-1, 70 parsePart(str, 8, 2), 71 parsePart(str, 11, 2), 72 parsePart(str, 14,2), 73 parsePart(str, 17, 2)); 74 75 if (str.length() == 25) { 76 int plusHr = parsePart(str, 20, 2); 77 int mul = str.charAt(19) == '+' ? -3600000 : 3600000; 78 calendar.setTimeInMillis(calendar.getTimeInMillis()+plusHr*mul); 79 } 80 81 return calendar.getTime(); 82 } 83 84 try { 85 return XML_DATE.newXMLGregorianCalendar(str).toGregorianCalendar().getTime(); 86 } catch (Exception ex) { 87 return new Date(); 88 } 89 } 90 91 public static synchronized String fromDate(Date date) { 92 calendar.setTime(date); 93 XMLGregorianCalendar xgc = XML_DATE.newXMLGregorianCalendar(calendar); 94 if (calendar.get(Calendar.MILLISECOND) == 0) xgc.setFractionalSecond(null); 95 return xgc.toXMLFormat(); 96 } 97 98 private static boolean checkLayout(String text, String pattern) { 99 if (text.length() != pattern.length()) return false; 100 for (int i=0; i<pattern.length(); i++) { 101 if (pattern.charAt(i) == 'x') continue; 102 if (pattern.charAt(i) != text.charAt(i)) return false; 103 } 104 return true; 105 } 106 107 private static int parsePart(String str, int off, int len) { 108 return Integer.valueOf(str.substring(off, off+len)); 109 } 110 111 } -
src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
60 60 import org.openstreetmap.josm.gui.dialogs.ConflictDialog; 61 61 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 62 62 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 63 import org.openstreetmap.josm.tools.DateUtils; 63 64 import org.openstreetmap.josm.tools.GBC; 64 65 import org.openstreetmap.josm.tools.ImageProvider; 65 66 … … 404 405 if (!n.tagged) { 405 406 doneNodes.add(n); 406 407 } 407 WayPoint wpt = new WayPoint(n.coor); 408 if ( n.timestamp != null)408 WayPoint wpt = new WayPoint(n.coor); 409 if (!n.isTimestampEmpty()) 409 410 { 410 wpt.attr.put("time", n.timestamp);411 wpt.attr.put("time", DateUtils.fromDate(n.getTimestamp())); 411 412 wpt.setTime(); 412 413 } 413 414 trkseg.add(wpt); … … 419 420 for (Node n : data.nodes) { 420 421 if (n.incomplete || n.deleted || doneNodes.contains(n)) continue; 421 422 WayPoint wpt = new WayPoint(n.coor); 422 if ( n.timestamp != null) {423 wpt.attr.put("time", n.timestamp);423 if (!n.isTimestampEmpty()) { 424 wpt.attr.put("time", DateUtils.fromDate(n.getTimestamp())); 424 425 wpt.setTime(); 425 426 } 426 427 if (n.keys != null && n.keys.containsKey("name")) { -
src/org/openstreetmap/josm/gui/layer/GpxLayer.java
67 67 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; 68 68 import org.openstreetmap.josm.gui.layer.markerlayer.AudioMarker; 69 69 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; 70 import org.openstreetmap.josm.tools.DateUtils; 70 71 import org.openstreetmap.josm.tools.DontShowAgainInfo; 71 72 import org.openstreetmap.josm.tools.GBC; 72 73 import org.openstreetmap.josm.tools.ImageProvider; … … 659 660 String timestr = p.getString("time"); 660 661 if(timestr != null) 661 662 { 662 timestr = timestr.replace("Z","+00:00"); 663 n.timestamp = timestr; 663 n.setTimestamp(DateUtils.fromString(timestr)); 664 664 } 665 665 ds.nodes.add(n); 666 666 w.nodes.add(n); -
src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java
35 35 import org.openstreetmap.josm.data.osm.DataSet; 36 36 import org.openstreetmap.josm.data.osm.OsmPrimitive; 37 37 import org.openstreetmap.josm.gui.SideButton; 38 import org.openstreetmap.josm.tools.DateUtils; 38 39 import org.openstreetmap.josm.tools.GBC; 39 40 import org.openstreetmap.josm.tools.ImageProvider; 40 41 import org.openstreetmap.josm.tools.Shortcut; … … 170 171 orderedHistory.addAll(cache.get(osm)); 171 172 data.setRowCount(0); 172 173 for (HistoryItem i : orderedHistory) 173 data.addRow(new Object[]{i.osm, i.osm.timestamp, i.visible});174 data.addRow(new Object[]{i.osm, DateUtils.fromDate(i.osm.getTimestamp()), i.visible}); 174 175 historyPane.setVisible(true); 175 176 notLoaded.setVisible(false); 176 177 } -
src/org/openstreetmap/josm/io/OsmReader.java
32 32 import org.openstreetmap.josm.data.osm.visitor.AddVisitor; 33 33 import org.openstreetmap.josm.data.osm.visitor.Visitor; 34 34 import org.openstreetmap.josm.gui.PleaseWaitDialog; 35 import org.openstreetmap.josm.tools.DateUtils; 35 36 import org.xml.sax.Attributes; 36 37 import org.xml.sax.InputSource; 37 38 import org.xml.sax.SAXException; … … 100 101 osm.modified = modified; 101 102 osm.selected = selected; 102 103 osm.deleted = deleted; 103 osm. timestamp = timestamp;104 osm.setTimestamp(getTimestamp()); 104 105 osm.user = user; 105 106 osm.visible = visible; 106 107 osm.version = version; … … 296 297 297 298 String time = atts.getValue("timestamp"); 298 299 if (time != null && time.length() != 0) { 299 /* Do not parse the date here since it wastes a HUGE amount of time. 300 * Moved into OsmPrimitive. 301 try { 302 current.timestamp = DateParser.parse(time); 303 } catch (ParseException e) { 304 e.printStackTrace(); 305 throw new SAXException(tr("Couldn''t read time format \"{0}\".",time)); 306 } 307 */ 308 current.timestamp = time; 300 current.setTimestamp(DateUtils.fromString(time)); 309 301 } 310 302 311 303 // user attribute added in 0.4 API -
src/org/openstreetmap/josm/io/OsmWriter.java
15 15 import org.openstreetmap.josm.data.osm.Changeset; 16 16 import org.openstreetmap.josm.data.osm.Way; 17 17 import org.openstreetmap.josm.data.osm.visitor.Visitor; 18 import org.openstreetmap.josm.tools.DateUtils; 18 19 19 20 /** 20 21 * Save the dataset into a stream as osm intern xml format. This is not using any … … 200 201 if (action != null) 201 202 out.print(" action='"+action+"'"); 202 203 } 203 if ( osm.timestamp != null) {204 out.print(" timestamp='"+ osm.timestamp+"'");204 if (!osm.isTimestampEmpty()) { 205 out.print(" timestamp='"+DateUtils.fromDate(osm.getTimestamp())+"'"); 205 206 } 206 207 // user and visible added with 0.4 API 207 208 if (osm.user != null) { -
src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
234 234 return true; // no merge needed. 235 235 } 236 236 if (my.realEqual(other, true)) { 237 Date myd = my. timestamp == null ? new Date(0) : my.getTimestamp();238 Date otherd = other. timestamp == null ? new Date(0) : other.getTimestamp();237 Date myd = my.getTimestamp(); 238 Date otherd = other.getTimestamp(); 239 239 240 240 // they differ in modified/timestamp combination only. Auto-resolve it. 241 241 merged.put(other, my); 242 242 if (myd.before(otherd)) { 243 243 my.modified = other.modified; 244 my. timestamp = other.timestamp;244 my.setTimestamp(other.getTimestamp()); 245 245 } 246 246 return true; // merge done. 247 247 } 248 248 if (my.id == other.id && my.id != 0) { 249 Date myd = my. timestamp == null ? new Date(0) : my.getTimestamp();250 Date otherd = other. timestamp == null ? new Date(0) : other.getTimestamp();249 Date myd = my.getTimestamp(); 250 Date otherd = other.getTimestamp(); 251 251 252 252 if (my.incomplete || other.incomplete) { 253 253 if (my.incomplete) { -
src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
3 3 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.text.ParseException;7 import java.text.SimpleDateFormat;8 import java.util.Arrays;9 6 import java.util.ArrayList; 7 import java.util.Arrays; 10 8 import java.util.Collection; 11 9 import java.util.Collections; 12 10 import java.util.Date; 13 11 import java.util.HashMap; 14 import java.util.HashSet;15 12 import java.util.Map; 16 13 import java.util.Map.Entry; 17 14 18 import org.openstreetmap.josm.data.osm.visitor.Visitor;19 import org.openstreetmap.josm.tools.DateParser;20 15 import org.openstreetmap.josm.Main; 16 import org.openstreetmap.josm.data.osm.visitor.Visitor; 21 17 import org.openstreetmap.josm.gui.mappaint.ElemStyle; 22 18 23 19 … … 129 125 */ 130 126 public volatile boolean highlighted = false; 131 127 128 private int timestamp; 129 130 public void setTimestamp(Date timestamp) { 131 this.timestamp = (int)(timestamp.getTime() / 1000); 132 } 133 132 134 /** 133 135 * Time of last modification to this object. This is not set by JOSM but 134 136 * read from the server and delivered back to the server unmodified. It is 135 137 * used to check against edit conflicts. 136 */ 137 public String timestamp = null; 138 * 139 */ 140 public Date getTimestamp() { 141 return new Date(timestamp * 1000l); 142 } 143 144 public boolean isTimestampEmpty() { 145 return timestamp == 0; 146 } 138 147 139 148 /** 140 * The timestamp is only parsed when this is really necessary, and this141 * is the cache for the result.142 */143 public Date parsedTimestamp = null;144 145 /**146 149 * If set to true, this object is incomplete, which means only the id 147 150 * and type is known (type is the objects instance class) 148 151 */ … … 182 185 } 183 186 184 187 /** 185 * Returns the timestamp for this object, or the current time if none is set.186 * Internally, parses the timestamp from XML into a Date object and caches it187 * for possible repeated calls.188 */189 public Date getTimestamp() {190 if (parsedTimestamp == null) {191 try {192 parsedTimestamp = DateParser.parse(timestamp);193 } catch (ParseException ex) {194 parsedTimestamp = new Date();195 }196 }197 return parsedTimestamp;198 }199 200 /**201 188 * Equal, if the id (and class) is equal. 202 189 * 203 190 * An primitive is equal to its incomplete counter part. … … 308 295 incomplete == osm.incomplete && 309 296 (semanticOnly || (modified == osm.modified)) && 310 297 deleted == osm.deleted && 311 (semanticOnly || (timestamp == null ? osm.timestamp==null : timestamp.equals(osm.timestamp))) &&298 (semanticOnly || timestamp == osm.timestamp) && 312 299 (semanticOnly || (version==osm.version)) && 313 300 (semanticOnly || (user == null ? osm.user==null : user==osm.user)) && 314 301 (semanticOnly || (visible == osm.visible)) && 315 302 (keys == null ? osm.keys==null : keys.equals(osm.keys)); 316 303 } 317 304 318 public String getTimeStr() {319 return timestamp == null ? null : new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp);320 }321 322 305 /** 323 306 * Updates the "tagged" flag. "keys" property should probably be made private 324 307 * to make sure this gets called when keys are set.