[OSM-dev] JOSM Images

Ben Gimpert ben at somethingmodern.com
Thu May 4 11:54:38 BST 2006


Since I'm feeling particularly self-loathing this morning, I went ahead
and wrote a strict ISO 8601 parser for JOSM's image layer-ing.  It also
has the expected more lenient "lazy" parsing as a fallback.  Here it is
as a patch for Imi:

<<BEGIN_PATCH
Index: josm/gui/layer/GeoImageLayer.java
===================================================================
--- josm/gui/layer/GeoImageLayer.java	(revision 101)
+++ josm/gui/layer/GeoImageLayer.java	(working copy)
@@ -70,6 +70,104 @@
 		EastNorth pos;
 		Icon icon;
 	}
+	
+	private static Date parseDateString(String s) {
+		// First check for strictly ISO 8601 formatted timestamps:
+		{
+			Pattern re = Pattern.compile("^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d):(\\d\\d)\\.(\\d+)(Z|([+-]\\d\\d:\\d\\d))$");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SS zzzzzzzzz");
+				double frac = Double.parseDouble("0." + m.group(7));
+				int millis = (int) (frac * 1000);
+				String parsable = m.group(1) + "/" + m.group(2) + "/" + m.group(3) + " " + m.group(4) + ":" + m.group(5) + ":" + m.group(6) + ":" + millis;
+				if (m.group(8).equalsIgnoreCase("Z")) {
+					parsable += " GMT+00:00";
+				}
+				else {
+					parsable += " GMT" + m.group(8);
+				}
+				return dateFormat.parse(parsable);
+			}
+		}
+		{
+			Pattern re = Pattern.compile("^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d):(\\d\\d)(Z|([+-]\\d\\d:\\d\\d))$");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss zzzzzzzzz");
+				String parsable = m.group(1) + "/" + m.group(2) + "/" + m.group(3) + " " + m.group(4) + ":" + m.group(5) + ":" + m.group(6);
+				if (m.group(7).equalsIgnoreCase("Z")) {
+					parsable += " GMT+00:00";
+				}
+				else {
+					parsable += " GMT" + m.group(7);
+				}
+				return dateFormat.parse(parsable);
+			}
+		}
+		{
+			Pattern re = Pattern.compile("^(\\d{4})-(\\d\\d)-(\\d\\d)T(\\d\\d):(\\d\\d)(Z|([+-]\\d\\d:\\d\\d))$");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm zzzzzzzzz");
+				String parsable = m.group(1) + "/" + m.group(2) + "/" + m.group(3) + " " + m.group(4) + ":" + m.group(5);
+				if (m.group(6).equalsIgnoreCase("Z")) {
+					parsable += " GMT+00:00";
+				}
+				else {
+					parsable += " GMT" + m.group(6);
+				}
+				return dateFormat.parse(parsable);
+			}
+		}
+		{
+			Pattern re = Pattern.compile("^(\\d{4})-(\\d\\d)-(\\d\\d)$");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
+				String parsable = m.group(1) + "/" + m.group(2) + "/" + m.group(3);
+				return dateFormat.parse(parsable);
+			}
+		}
+		{
+			Pattern re = Pattern.compile("^(\\d{4})-(\\d\\d)$");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM");
+				String parsable = m.group(1) + "/" + m.group(2);
+				return dateFormat.parse(parsable);
+			}
+		}
+		{
+			Pattern re = Pattern.compile("^\\d{4}$");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
+				String parsable = m.group(1);
+				return dateFormat.parse(parsable);
+			}
+		}
+		// Now check for lazy-er formats:
+		{
+			Pattern re = Pattern.compile("(\\d\\d/\\d\\d/\\d{4}).(\\d\\d:\\d\\d:\\d\\d)");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
+				String parsable = m.group(1) + " " + m.group(2);
+				return dateFormat.parse(parsable);
+			}
+		}
+		{
+			Pattern re = Pattern.compile("(\\d\\d)-(\\d\\d)-(\\d{4}).(\\d\\d:\\d\\d:\\d\\d)");
+			Matcher m = re.matcher(s);
+			if (m.matches()) {
+				SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
+				String parsable = m.group(1) + "/" + m.group(2) + "/" + m.group(3) + " " + m.group(4);
+				return dateFormat.parse(parsable);
+			}
+		}
+		return null;
+	}
 
 	private static final class Loader extends PleaseWaitRunnable {
 		boolean cancelled = false;
@@ -87,16 +185,15 @@
 
 			// check the gps layer for time loops (and process it on the way)
 			Date last = null;
-			Pattern reg = Pattern.compile("(\\d\\d/\\d\\d/\\d{4}).(\\d\\d:\\d\\d:\\d\\d)");
 			try {
 				for (Collection<GpsPoint> c : gpsLayer.data) {
 					for (GpsPoint p : c) {
 						if (p.time == null)
 							throw new IOException("No time for point "+p.latlon.lat()+","+p.latlon.lon());
-						Matcher m = reg.matcher(p.time);
-						if (!m.matches())
+						Date d = parseDateString(p.time);
+						if (d == null) {
 							throw new IOException("Cannot read time from point "+p.latlon.lat()+","+p.latlon.lon());
-						Date d = dateFormat.parse(m.group(1)+" "+m.group(2));
+						}
 						gps.add(new TimedPoint(d, p.eastNorth));
 						if (last != null && last.after(d))
 							throw new IOException("Time loop in gps data.");
@@ -152,7 +249,6 @@
 	private long delta = Long.parseLong(Main.pref.get("tagimages.delta", "0"));
 	private long gpstimezone = Long.parseLong(Main.pref.get("tagimages.gpstimezone", "0"))*60*60*1000;
 	private boolean mousePressed = false;
-	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
 	private MouseAdapter mouseAdapter;
 
 	public static final class GpsTimeIncorrect extends Exception {
<<EOF_PATCH


On Thu, May 04, 2006 at 10:17:54AM +0100, Andy Robinson wrote:
> Yes, the gpx format for <time> requires:
> 
> "Creation/modification timestamp for element. Date and time in are in
> Univeral Coordinated Time (UTC), not local time! Conforms to ISO 8601
> specification for date/time representation. Fractional seconds are allowed
> for millisecond timing in tracklogs."
> 
> ie 2006-04-29T05:51:09Z
> 
> http://www.w3.org/TR/NOTE-datetime for ref.
> 
> Andy
> 
> Andy Robinson
> Andy_J_Robinson at blueyonder.co.uk 
> 
> >-----Original Message-----
> >From: dev-bounces at openstreetmap.org [mailto:dev-bounces at openstreetmap.org]
> >On Behalf Of Immanuel Scholz
> >Sent: 04 May 2006 09:47
> >To: dev at openstreetmap.org
> >Subject: Re: [OSM-dev] JOSM Images
> >
> >Hi,
> >
> >
> >> If I convert the file so that the dates are like 05/03/2006 16:32:47
> >> then everything works, so it's clearly a problem with parsing the time
> >> in the .gpx file.
> >
> >Yep. Exactly this. I used the "poor men's date parsing", which means it
> >currently can only read time that is in exactly your described format.
> >
> >This is a bug for sure (or call it "missing feature" ;), JOSM should
> >rather use some more general way to try to parse in the date time.
> >
> >Unfortunatly, I start my 4-week-holiday tomorrow at 5:30am and haven't
> >packed yet, so it is very unlikely that you will see this implemented
> >before end of may :-(  (Maybe if someone bring a laptop with eclipse and
> >inet-access along to the IoW ;-D  )
> >
> >
> >> I have one feature request that would make a lot of difference.  I've
> >> started adding a reference to the image as a tag on the relevant way.
> >
> >Wouldn't it be better to make it a reference on a node? (Point Of Interest)
> >
> >
> >> It would be really nice if there was some way to select the name of
> >> the image file (without the path?) so that it can be pasted into a
> >> key-value field.  Something like Ctrl+C when the image is selected
> >> would do.  This would save time and reduce typing errors.
> >
> >Yea... can you add both things (the parsing thing as bug, this as an
> >feature) to trac?
> >
> >
> >Ciao, Imi.
> >
> >
> >
> >_______________________________________________
> >dev mailing list
> >dev at openstreetmap.org
> >http://lists.openstreetmap.org/cgi-bin/mailman/listinfo/dev
> 
> 
> 
> 
> _______________________________________________
> dev mailing list
> dev at openstreetmap.org
> http://lists.openstreetmap.org/cgi-bin/mailman/listinfo/dev




More information about the dev mailing list