Index: trunk/src/org/openstreetmap/josm/io/NoteImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/NoteImporter.java	(revision 9744)
+++ trunk/src/org/openstreetmap/josm/io/NoteImporter.java	(revision 9746)
@@ -37,17 +37,10 @@
         }
         try (InputStream is = Compression.getUncompressedFileInputStream(file)) {
-            final List<Note> fileNotes = new NoteReader(is).parse();
-
-            List<NoteLayer> noteLayers = null;
-            if (Main.map != null) {
-                noteLayers = Main.map.mapView.getLayersOfType(NoteLayer.class);
-            }
-            if (noteLayers != null && !noteLayers.isEmpty()) {
-                noteLayers.get(0).getNoteData().addNotes(fileNotes);
-            } else {
+            final NoteLayer layer = loadLayer(is, file, file.getName(), progressMonitor);
+            if (!Main.map.mapView.hasLayer(layer)) {
                 GuiHelper.runInEDT(new Runnable() {
                     @Override
                     public void run() {
-                        Main.main.addLayer(new NoteLayer(fileNotes, file.getName()));
+                        Main.main.addLayer(layer);
                     }
                 });
@@ -59,3 +52,31 @@
         }
     }
+
+    /**
+     * Load note layer from InputStream.
+     * @param in input stream
+     * @param associatedFile filename of data (can be <code>null</code> if the stream does not come from a file)
+     * @param layerName name of generated layer
+     * @param progressMonitor handler for progress monitoring and canceling
+     * @return note layer
+     * @throws IOException
+     * @throws SAXException
+     * @since 9746
+     */
+    public NoteLayer loadLayer(InputStream in, final File associatedFile, final String layerName, ProgressMonitor progressMonitor)
+            throws SAXException, IOException {
+        final List<Note> fileNotes = new NoteReader(in).parse();
+        List<NoteLayer> noteLayers = null;
+        if (Main.map != null) {
+            noteLayers = Main.map.mapView.getLayersOfType(NoteLayer.class);
+        }
+        final NoteLayer layer;
+        if (noteLayers != null && !noteLayers.isEmpty()) {
+            layer = noteLayers.get(0);
+            layer.getNoteData().addNotes(fileNotes);
+        } else {
+            layer = new NoteLayer(fileNotes, associatedFile != null ? associatedFile.getName() : tr("Notes"));
+        }
+        return layer;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/io/session/GenericSessionExporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/GenericSessionExporter.java	(revision 9744)
+++ trunk/src/org/openstreetmap/josm/io/session/GenericSessionExporter.java	(revision 9746)
@@ -221,4 +221,4 @@
     }
 
-    protected abstract void addDataFile(OutputStream out);
+    protected abstract void addDataFile(OutputStream out) throws IOException;
 }
Index: trunk/src/org/openstreetmap/josm/io/session/NoteSessionExporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/NoteSessionExporter.java	(revision 9746)
+++ trunk/src/org/openstreetmap/josm/io/session/NoteSessionExporter.java	(revision 9746)
@@ -0,0 +1,31 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.session;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.openstreetmap.josm.gui.layer.NoteLayer;
+import org.openstreetmap.josm.io.NoteWriter;
+
+/**
+ * Session exporter for {@link NoteLayer}.
+ * @since 9746
+ */
+public class NoteSessionExporter extends GenericSessionExporter<NoteLayer> {
+
+    /**
+     * Constructs a new {@code NoteSessionExporter}.
+     * @param layer Note layer to export
+     */
+    public NoteSessionExporter(NoteLayer layer) {
+        super(layer, "osm-notes", "0.1", "osn");
+    }
+
+    @Override
+    protected void addDataFile(OutputStream out) throws IOException {
+        @SuppressWarnings("resource")
+        NoteWriter writer = new NoteWriter(out);
+        writer.write(layer.getNoteData());
+        writer.flush();
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/session/NoteSessionImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/NoteSessionImporter.java	(revision 9746)
+++ trunk/src/org/openstreetmap/josm/io/session/NoteSessionImporter.java	(revision 9746)
@@ -0,0 +1,53 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.session;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.NoteLayer;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.IllegalDataException;
+import org.openstreetmap.josm.io.NoteImporter;
+import org.openstreetmap.josm.io.session.SessionReader.ImportSupport;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+/**
+ * Session importer for {@link NoteLayer}.
+ * @since 9746
+ */
+public class NoteSessionImporter implements SessionLayerImporter {
+
+    @Override
+    public Layer load(Element elem, ImportSupport support, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
+        String version = elem.getAttribute("version");
+        if (!"0.1".equals(version)) {
+            throw new IllegalDataException(tr("Version ''{0}'' of meta data for note layer is not supported. Expected: 0.1", version));
+        }
+        try {
+            XPathFactory xPathFactory = XPathFactory.newInstance();
+            XPath xpath = xPathFactory.newXPath();
+            XPathExpression fileExp = xpath.compile("file/text()");
+            String fileStr = (String) fileExp.evaluate(elem, XPathConstants.STRING);
+            if (fileStr == null || fileStr.isEmpty()) {
+                throw new IllegalDataException(tr("File name expected for layer no. {0}", support.getLayerIndex()));
+            }
+
+            NoteImporter importer = new NoteImporter();
+            try (InputStream in = support.getInputStream(fileStr)) {
+                return importer.loadLayer(in, support.getFile(fileStr), support.getLayerName(), progressMonitor);
+            }
+        } catch (XPathExpressionException | SAXException e) {
+            throw new IllegalDataException(e);
+        }
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/session/SessionReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 9744)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 9746)
@@ -75,4 +75,5 @@
         registerSessionLayerImporter("geoimage", GeoImageSessionImporter.class);
         registerSessionLayerImporter("markers", MarkerSessionImporter.class);
+        registerSessionLayerImporter("osm-notes", NoteSessionImporter.class);
     }
 
Index: trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java	(revision 9744)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java	(revision 9746)
@@ -35,4 +35,5 @@
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.NoteLayer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.TMSLayer;
@@ -71,4 +72,5 @@
         registerSessionLayerExporter(GeoImageLayer.class, GeoImageSessionExporter.class);
         registerSessionLayerExporter(MarkerLayer.class, MarkerSessionExporter.class);
+        registerSessionLayerExporter(NoteLayer.class, NoteSessionExporter.class);
     }
 
Index: trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 9744)
+++ trunk/src/org/openstreetmap/josm/tools/date/DateUtils.java	(revision 9746)
@@ -80,9 +80,11 @@
      */
     public static synchronized long tsFromString(String str) throws UncheckedParseException {
-        // "2007-07-25T09:26:24{Z|{+|-}01:00}"
+        // "2007-07-25T09:26:24{Z|{+|-}01[:00]}"
         if (checkLayout(str, "xxxx-xx-xxTxx:xx:xxZ") ||
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx") ||
                 checkLayout(str, "xxxx:xx:xx xx:xx:xx") ||
                 checkLayout(str, "xxxx-xx-xx xx:xx:xx UTC") ||
+                checkLayout(str, "xxxx-xx-xxTxx:xx:xx+xx") ||
+                checkLayout(str, "xxxx-xx-xxTxx:xx:xx-xx") ||
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx+xx:00") ||
                 checkLayout(str, "xxxx-xx-xxTxx:xx:xx-xx:00")) {
@@ -97,5 +99,5 @@
             c.set(Calendar.MILLISECOND, 0);
 
-            if (str.length() == 25) {
+            if (str.length() == 22 || str.length() == 25) {
                 int plusHr = parsePart2(str, 20);
                 int mul = str.charAt(19) == '+' ? -3600000 : 3600000;
