diff --git a/athenasub/include/athenasub/athenatime.h b/athenasub/include/athenasub/athenatime.h
index a45a1a2d158ad7c070e3738944e0960912dbe317..3686bf75c5db20f37d2feaf12e5b668d4da55b7c 100644
--- a/athenasub/include/athenasub/athenatime.h
+++ b/athenasub/include/athenasub/athenatime.h
@@ -47,10 +47,17 @@ namespace Athenasub {
 	public:
 		Time();
 		Time(int milliseconds);
+		Time(const String& timestamp);
+		Time(int hours,int minutes,int seconds,int milliseconds);
 
 		int GetMS() const;
 		void SetMS(int milliseconds);
 
+		int GetHoursComponent() const;
+		int GetMinutesComponent() const;
+		int GetSecondsComponent() const;
+		int GetMillisecondsComponent() const;
+
 		String GetString(int ms_precision=3,int h_precision=1) const;
 		void ParseString(const String &data);
 
diff --git a/athenasub/src/athenatime.cpp b/athenasub/src/athenatime.cpp
index 432efc83a8c6a056407188167260acec0ab22996..5b66456e79544001c03de6444604d6b6ef402bf3 100644
--- a/athenasub/src/athenatime.cpp
+++ b/athenasub/src/athenatime.cpp
@@ -35,6 +35,7 @@
 
 #include "athenatime.h"
 #include "utils.h"
+#include "exception.h"
 using namespace Athenasub;
 
 
@@ -50,6 +51,16 @@ Time::Time(int milliseconds)
 	SetMS(milliseconds);
 }
 
+Time::Time(const String& timestamp)
+{
+	ParseString(timestamp);
+}
+
+Time::Time(int hours,int minutes,int seconds,int milliseconds)
+{
+	SetMS(hours*3600000 + minutes*60000 + seconds*1000 + milliseconds);
+}
+
 
 ///////////////////
 // Getters/setters
@@ -70,7 +81,7 @@ String Time::GetString(int ms_precision,int h_precision) const
 {
 	// Enforce sanity
 	ms_precision = Mid(0,ms_precision,3);
-	h_precision = Mid(0,h_precision,2);
+	h_precision = Max(0,h_precision);
 
 	// Generate values
 	int _ms = GetMS();
@@ -81,9 +92,15 @@ String Time::GetString(int ms_precision,int h_precision) const
 	int s = _ms / 1000;
 	_ms -= s*1000;
 
+	// Find maximum hour value
+	int maxH = 0;
+	for (int i=0;i<h_precision;i++) {
+		maxH = maxH * 10 + 9;
+	}
+
 	// Cap hour value
-	if (h > 9 && h_precision == 1) {
-		h = 9;
+	if (h > maxH) {
+		h = maxH;
 		min = 59;
 		s = 59;
 		_ms = 999;
@@ -95,33 +112,37 @@ String Time::GetString(int ms_precision,int h_precision) const
 	else if (ms_precision == 0) _ms = 0;
 
 	// Asserts
-	assert(h   >= 0 && h   <= 9);
+	assert(h   >= 0 && h   <= maxH);
 	assert(min >= 0 && min <= 59);
 	assert(s   >= 0 && s   <= 59);
 	assert(_ms >= 0 && _ms <= 999);
 
 	// Get write buffer
 	String final;
-	size_t size = 7+h_precision+ms_precision;
+	size_t size = 5 + (h_precision > 0 ? h_precision+1 : 0) + (ms_precision > 0 ? ms_precision + 1 : 0);
 	size_t pos = 0;
 	//wxChar *buffer = final.GetWriteBuf(size);
 	Character temp[16];
 	final.resize(size);
 
 	// Write time
-	final.WriteNumber(temp,h,h_precision,pos);
-	final.WriteChar(':',pos);
+	if (h_precision > 0) {
+		final.WriteNumber(temp,h,h_precision,pos);
+		final.WriteChar(':',pos);
+	}
 	final.WriteNumber(temp,min,2,pos);
 	final.WriteChar(':',pos);
 	final.WriteNumber(temp,s,2,pos);
-	final.WriteChar('.',pos);
-	final.WriteNumber(temp,_ms,ms_precision,pos);
+	if (ms_precision > 0) {
+		final.WriteChar('.',pos);
+		final.WriteNumber(temp,_ms,ms_precision,pos);
+	}
 
 	// Write terminator
 	//final.WriteText("\0",1,pos);
 
 	// Restore string's state and return
-	final.SetSize(pos-1);
+	//final.SetSize(pos-1);
 	return final;
 }
 
@@ -157,7 +178,8 @@ void Time::ParseString(const String &data)
 		}
 
 		// Got a digit
-		else {
+		else if (cur != ' ') {
+			if (cur < '0' || cur > '9') THROW_ATHENA_EXCEPTION(Exception::Parse_Error);
 			curValue = curValue * 10 + (int)(cur-'0');
 			nDigits++;
 
diff --git a/unit_test/src/athenasub/test_time.cpp b/unit_test/src/athenasub/test_time.cpp
index f63070d1962d2cba8bd681170ea75c466405d75e..e2991537f36b9ea1ac2527f7e2ef70e35ff902e2 100644
--- a/unit_test/src/athenasub/test_time.cpp
+++ b/unit_test/src/athenasub/test_time.cpp
@@ -50,6 +50,7 @@ class AthenasubTimeTest : public CppUnit::TestFixture {
 	CPPUNIT_TEST(testOperators);
 	CPPUNIT_TEST(testSetGet);
 	CPPUNIT_TEST(testParse);
+	CPPUNIT_TEST(testToString);
 	CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -109,45 +110,45 @@ public:
 
 	void testParse()
 	{
-		Time a;
-		a.ParseString("0");
-		CPPUNIT_ASSERT(a.GetMS() == 0);
-		a.ParseString("5");
-		CPPUNIT_ASSERT(a.GetMS() == 5000);
-		a.ParseString("5.0");
-		CPPUNIT_ASSERT(a.GetMS() == 5000);
-		a.ParseString("5,0");
-		CPPUNIT_ASSERT(a.GetMS() == 5000);
-		a.ParseString("5.00");
-		CPPUNIT_ASSERT(a.GetMS() == 5000);
-		a.ParseString("5.000");
-		CPPUNIT_ASSERT(a.GetMS() == 5000);
-		a.ParseString("5.1");
-		CPPUNIT_ASSERT(a.GetMS() == 5100);
-		a.ParseString("5.12");
-		CPPUNIT_ASSERT(a.GetMS() == 5120);
-		a.ParseString("5.123");
-		CPPUNIT_ASSERT(a.GetMS() == 5123);
-		a.ParseString("5,123");
-		CPPUNIT_ASSERT(a.GetMS() == 5123);
-		a.ParseString("5,1234");
-		CPPUNIT_ASSERT(a.GetMS() == 5123);
-		a.ParseString("5,");
-		CPPUNIT_ASSERT(a.GetMS() == 5000);
-		a.ParseString("05.12");
-		CPPUNIT_ASSERT(a.GetMS() == 5120);
-		a.ParseString("0:05.12");
-		CPPUNIT_ASSERT(a.GetMS() == 5120);
-		a.ParseString("0:15.12");
-		CPPUNIT_ASSERT(a.GetMS() == 15120);
-		a.ParseString("1:15.12");
-		CPPUNIT_ASSERT(a.GetMS() == 75120);
-		a.ParseString("11:15.12");
-		CPPUNIT_ASSERT(a.GetMS() == 675120);
-		a.ParseString("2:11:15.12");
-		CPPUNIT_ASSERT(a.GetMS() == 675120+7200000);
-		a.ParseString("10:11:15.12");
-		CPPUNIT_ASSERT(a.GetMS() == 675120+36000000);
+		CPPUNIT_ASSERT(Time("0").GetMS() == 0);
+		CPPUNIT_ASSERT(Time("5").GetMS() == 5000);
+		CPPUNIT_ASSERT(Time("5.0").GetMS() == 5000);
+		CPPUNIT_ASSERT(Time("5,0").GetMS() == 5000);
+		CPPUNIT_ASSERT(Time("5.00").GetMS() == 5000);
+		CPPUNIT_ASSERT(Time("5.000").GetMS() == 5000);
+		CPPUNIT_ASSERT(Time("5.1").GetMS() == 5100);
+		CPPUNIT_ASSERT(Time("5.12").GetMS() == 5120);
+		CPPUNIT_ASSERT(Time("5.123").GetMS() == 5123);
+		CPPUNIT_ASSERT(Time("5,123").GetMS() == 5123);
+		CPPUNIT_ASSERT(Time("5,1234").GetMS() == 5123);
+		CPPUNIT_ASSERT(Time("5,").GetMS() == 5000);
+		CPPUNIT_ASSERT(Time("5.").GetMS() == 5000);
+		CPPUNIT_ASSERT(Time("05.12").GetMS() == 5120);
+		CPPUNIT_ASSERT(Time("0:05.12").GetMS() == 5120);
+		CPPUNIT_ASSERT(Time("0:15.12").GetMS() == 15120);
+		CPPUNIT_ASSERT(Time("1:15.12").GetMS() == 75120);
+		CPPUNIT_ASSERT(Time("11:15.12").GetMS() == 675120);
+		CPPUNIT_ASSERT(Time("2:11:15.12").GetMS() == 675120+7200000);
+		CPPUNIT_ASSERT(Time("10:11:15.12").GetMS() == 675120+36000000);
+		CPPUNIT_ASSERT(Time(" 10 : 11 : 15 . 12 ").GetMS() == 675120+36000000);
+		CPPUNIT_ASSERT_THROW(Time("10:1-1:15.12"),Athenasub::Exception);
+	}
+
+	void testToString()
+	{
+		Time a(1,23,45,678);
+		Time b(11,23,45,678);
+		Time c(111,23,45,678);
+		CPPUNIT_ASSERT(a.GetString() == "1:23:45.678");
+		CPPUNIT_ASSERT(a.GetString(2,1) == "1:23:45.67");
+		CPPUNIT_ASSERT(a.GetString(3,2) == "01:23:45.678");
+		CPPUNIT_ASSERT(a.GetString(0,1) == "1:23:45");
+		CPPUNIT_ASSERT(a.GetString(0,0) == "59:59");
+		CPPUNIT_ASSERT(b.GetString(3,2) == "11:23:45.678");
+		CPPUNIT_ASSERT(b.GetString() == "9:59:59.999");
+		CPPUNIT_ASSERT(b.GetString(2,1) == "9:59:59.99");
+		CPPUNIT_ASSERT(c.GetString(3,2) == "99:59:59.999");
+		CPPUNIT_ASSERT(c.GetString(3,3) == "111:23:45.678");
 	}
 };