diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocation.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocation.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fb4f23d85e0e08852f2032b5a1c491970b3c3f2
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocation.java
@@ -0,0 +1,60 @@
+package tdt4140.gr1800.app.core;
+
+public class GeoLocation extends TimedTaggedImpl implements GeoLocated, Timed, Tagged {
+
+	private LatLong latLong;
+
+	public LatLong getLatLong() {
+		return latLong;
+	}
+
+	public void setLatLong(LatLong latLong) {
+		this.latLong = latLong;
+	}
+
+	private int elevation;
+	
+	public int getElevation() {
+		return elevation;
+	}
+	
+	private String name, description;
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public String getDescription() {
+		return description;
+	}
+	
+	public void setDescription(String description) {
+		this.description = description;
+	}
+	
+	//
+	
+	private Tags tags = null;
+
+	@Override
+	public boolean hasTags(String... tags) {
+		return this.tags != null && this.tags.hasTags(tags);
+	}
+	
+	public void addTags(String... tags) {
+		if (this.tags == null) {
+			this.tags = new Tags();
+		}
+		this.tags.addTags(tags);
+	}
+	
+	public void removeTags(String... tags) {
+		if (this.tags != null) {
+			this.tags.removeTags(tags);
+		}
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocations.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocations.java
index ede9cf2de0f5207db991520918932e4245076cf3..8eeaf5c13593ce488998caa0ce4e0aa2625ccf14 100644
--- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocations.java
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocations.java
@@ -1,16 +1,13 @@
 package tdt4140.gr1800.app.core;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Optional;
-import java.util.Set;
 import java.util.stream.Collectors;
 
-public class GeoLocations implements Iterable<GeoLocated>, Tagged {
+public class GeoLocations extends TimedTaggedImpl implements Iterable<GeoLocated>, Tagged, Timed {
 
 	private String name;
 	
@@ -21,7 +18,7 @@ public class GeoLocations implements Iterable<GeoLocated>, Tagged {
 	public void setName(String name) {
 		this.name = name;
 	}
-	
+
 	private Collection<GeoLocated> locations = new ArrayList<GeoLocated>();
 	private boolean path = false;
 	
@@ -35,7 +32,7 @@ public class GeoLocations implements Iterable<GeoLocated>, Tagged {
 		this(latLongs);
 		setName(name);
 	}
-	
+
 	public boolean isPath() {
 		return path;
 	}
@@ -85,26 +82,4 @@ public class GeoLocations implements Iterable<GeoLocated>, Tagged {
 	public Iterator<GeoLocated> iterator() {
 		return locations.iterator();
 	}
-	
-	//
-	
-	private Set<String> tags = null;
-
-	@Override
-	public boolean hasTags(String... tags) {
-		return this.tags != null && this.tags.containsAll(Arrays.asList(tags));
-	}
-	
-	public void addTags(String... tags) {
-		if (this.tags == null) {
-			this.tags = new HashSet<>();
-		}
-		this.tags.addAll(Arrays.asList(tags));
-	}
-	
-	public void removeTags(String... tags) {
-		if (this.tags != null) {
-			this.tags.removeAll(Arrays.asList(tags));
-		}
-	}
 }
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Tagged.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Tagged.java
index 8f1ad456b2b2ec7796ef8eab67c5a71434ee3dd4..f6bacd1841a99a9ef7d742f6aa1551bc1825ad37 100644
--- a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Tagged.java
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Tagged.java
@@ -2,4 +2,6 @@ package tdt4140.gr1800.app.core;
 
 public interface Tagged {
 	public boolean hasTags(String... tags);
+	public void addTags(String... tags);	
+	public void removeTags(String... tags);
 }
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Tags.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Tags.java
new file mode 100644
index 0000000000000000000000000000000000000000..8fdc743865e5c5585c770b3c5d92a9156b4a0e2f
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Tags.java
@@ -0,0 +1,40 @@
+package tdt4140.gr1800.app.core;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+public class Tags implements Tagged {
+
+	private Collection<String> tags = null;
+
+	public Tags(String... tags) {
+		addTags(tags);
+	}
+	
+	public int getTagCount() {
+		return (tags == null ? 0 : tags.size());
+	}
+	
+	@Override
+	public boolean hasTags(String... tags) {
+		return this.tags != null && this.tags.containsAll(Arrays.asList(tags));
+	}
+	
+	public void addTags(String... tags) {
+		if (this.tags == null && tags != null && tags.length > 0) {
+			this.tags = new ArrayList<>();
+		}
+		for (int i = 0; i < tags.length; i++) {
+			if (! this.tags.contains(tags[i])) {
+				this.tags.add(tags[i]);
+			}
+		}
+	}
+	
+	public void removeTags(String... tags) {
+		if (this.tags != null) {
+			this.tags.removeAll(Arrays.asList(tags));
+		}
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Timed.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Timed.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf2c78abfba28d92fba015c4c1ba9c25d170b5a2
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/Timed.java
@@ -0,0 +1,37 @@
+package tdt4140.gr1800.app.core;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+
+public interface Timed {
+
+	public ZoneId getZone();
+	public void setZone(ZoneId zone);
+
+	default 	public void setZone(String zone) {
+		setZone(ZoneId.of(zone));
+	}
+
+	public LocalDate getDate();
+	
+	public void setDate(LocalDate date);
+
+	default public void setDate(String date) {
+		setDate(LocalDate.parse(date));
+	}
+
+	public LocalTime getTime();
+	
+	public void setTime(LocalTime time);
+
+	default public void setTime(String time) {
+		setTime(LocalTime.parse(time));
+	}
+
+	default public void setDateTime(LocalDateTime dateTime) {
+		setDate(dateTime.toLocalDate());
+		setTime(dateTime.toLocalTime());
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/TimedImpl.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/TimedImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3d85d94699cf6028ec9feda831a8d63abf7c940
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/TimedImpl.java
@@ -0,0 +1,37 @@
+package tdt4140.gr1800.app.core;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZoneId;
+
+public class TimedImpl implements Timed {
+	
+	private ZoneId zone;
+
+	public ZoneId getZone() {
+		return zone;
+	}
+	
+	public void setZone(ZoneId zone) {
+		this.zone = zone;
+	}
+	
+	private LocalDate date;
+	private LocalTime time;
+
+	public LocalDate getDate() {
+		return date;
+	}
+
+	public void setDate(LocalDate date) {
+		this.date = date;
+	}
+
+	public LocalTime getTime() {
+		return time;
+	}
+
+	public void setTime(LocalTime time) {
+		this.time = time;
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/TimedTaggedImpl.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/TimedTaggedImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..09a651108a7db812c0edc763de25a55d4c5088a3
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/TimedTaggedImpl.java
@@ -0,0 +1,27 @@
+package tdt4140.gr1800.app.core;
+
+public class TimedTaggedImpl extends TimedImpl implements Tagged {
+	
+	private Tags tags = null;
+
+	@Override
+	public boolean hasTags(String... tags) {
+		return this.tags != null && this.tags.hasTags(tags);
+	}
+	
+	public void addTags(String... tags) {
+		if (this.tags == null) {
+			this.tags = new Tags();
+		}
+		this.tags.addTags(tags);
+	}
+	
+	public void removeTags(String... tags) {
+		if (this.tags != null) {
+			this.tags.removeTags(tags);
+			if (this.tags.getTagCount() == 0) {
+				this.tags = null;
+			}
+		}
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ef8065ef3ffbb9f07a46c9a5ad2cb74d78ecb6f
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationTest.java
@@ -0,0 +1,22 @@
+package tdt4140.gr1800.app.core;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class GeoLocationTest extends TimedTaggedTest {
+
+	private GeoLocation geoLocation;
+	
+	@Before
+	public void setUp() {
+		setUp(geoLocation = new GeoLocation());
+	}
+	
+	@Test
+	public void testSetLatLong() {
+		LatLong latLong = new LatLong(63, 10);
+		geoLocation.setLatLong(latLong);
+		Assert.assertEquals(latLong, geoLocation.getLatLong());
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsTest.java
index 1af22c713eb354a464788ff6f6a944504b8edbb6..689aaeec74cdba28006ce1c099cc1e6dfbcf419a 100644
--- a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsTest.java
+++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsTest.java
@@ -7,13 +7,13 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-public class GeoLocationsTest {
+public class GeoLocationsTest extends TimedTaggedTest {
 
 	private GeoLocations geoLocations;
 	
 	@Before
 	public void setUp() {
-		geoLocations = new GeoLocations();
+		setUp(geoLocations = new GeoLocations());
 	}
 
 	@Test
diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/TimedTaggedTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/TimedTaggedTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e16bc4c9d548ff5e1f06e070a83bcbc0413f85c
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/TimedTaggedTest.java
@@ -0,0 +1,68 @@
+package tdt4140.gr1800.app.core;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TimedTaggedTest {
+
+	private TimedTaggedImpl timedTagged;
+	
+	protected void setUp(TimedTaggedImpl timedTagged) {
+		this.timedTagged = timedTagged;
+	}
+	
+	@Before
+	public void setUp() {
+		setUp(new TimedTaggedImpl());
+	}
+
+	@Test
+	public void testTaggedSetTime() {
+		LocalTime now = LocalTime.now();
+		timedTagged.setTime(now);
+		Assert.assertEquals(now, timedTagged.getTime());
+	}
+	
+	@Test
+	public void testTaggedSetDate() {
+		LocalDate now = LocalDate.now();
+		timedTagged.setDate(now);
+		Assert.assertEquals(now, timedTagged.getDate());
+	}
+	
+	@Test
+	public void testTaggedSetDateTime() {
+		LocalDateTime now = LocalDateTime.now();
+		timedTagged.setDateTime(now);
+		Assert.assertEquals(now.toLocalDate(), timedTagged.getDate());
+		Assert.assertEquals(now.toLocalTime(), timedTagged.getTime());
+	}
+
+	@Test
+	public void testTaggedAdd() {
+		timedTagged.addTags("en", "to");
+		Assert.assertTrue(timedTagged.hasTags("en"));
+		Assert.assertTrue(timedTagged.hasTags("to"));
+		Assert.assertTrue(timedTagged.hasTags("en", "to"));
+		timedTagged.addTags("tre");
+		Assert.assertTrue(timedTagged.hasTags("en", "to"));
+		Assert.assertTrue(timedTagged.hasTags("tre"));
+	}
+	
+	@Test
+	public void testTaggedRemove() {
+		timedTagged.addTags("en", "en", "to");
+		timedTagged.removeTags("en");
+		Assert.assertFalse(timedTagged.hasTags("en"));
+		Assert.assertTrue(timedTagged.hasTags("to"));
+		timedTagged.removeTags("to");
+		Assert.assertFalse(timedTagged.hasTags("to"));
+		timedTagged.removeTags("tre");
+		Assert.assertFalse(timedTagged.hasTags("tre"));
+	}
+}