diff --git a/aegilib/aegilib.vcproj b/aegilib/aegilib.vcproj
index 742f085a30e872996fe3076aa665cc5ead805371..a0138d5969f1e14c692d3807ec30163c48f5f7a1 100644
--- a/aegilib/aegilib.vcproj
+++ b/aegilib/aegilib.vcproj
@@ -296,6 +296,10 @@
 				RelativePath=".\src\text_file_reader.h"
 				>
 			</File>
+			<File
+				RelativePath=".\src\time.cpp"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="Formats"
diff --git a/aegilib/include/aegilib/aegilib.h b/aegilib/include/aegilib/aegilib.h
index 56642a8644382f3899c8f3a845bb558eb3b0b32c..c456871de51c4d56b99d04eee0806fe238693b12 100644
--- a/aegilib/include/aegilib/aegilib.h
+++ b/aegilib/include/aegilib/aegilib.h
@@ -46,3 +46,17 @@
 #include "manipulator.h"
 #include "section.h"
 #include "section_entry_dialogue.h"
+#include "time.h"
+
+
+//////////
+// Macros
+#ifndef MAX
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MID
+#define MID(a,b,c) MIN(MAX((a),(b)),(c))
+#endif
\ No newline at end of file
diff --git a/aegilib/include/aegilib/section_entry_dialogue.h b/aegilib/include/aegilib/section_entry_dialogue.h
index fbbe4ae1dd04e1f774b2299f7ffda49c06526153..2415684301fa0e59f89b97203cc3c6fd4182410d 100644
--- a/aegilib/include/aegilib/section_entry_dialogue.h
+++ b/aegilib/include/aegilib/section_entry_dialogue.h
@@ -36,8 +36,8 @@
 
 #pragma once
 #include "exception.h"
-#include "section_entry.h"
 #include "time.h"
+#include "section_entry.h"
 
 
 namespace Aegilib {
diff --git a/aegilib/include/aegilib/time.h b/aegilib/include/aegilib/time.h
index ca59747035cd153673f62b987fb6c707d1c4e5ac..0a6f521e84d078a89153b7fe3c5afd047b647387 100644
--- a/aegilib/include/aegilib/time.h
+++ b/aegilib/include/aegilib/time.h
@@ -34,6 +34,7 @@
 //
 
 #pragma once
+#include "aegistring.h"
 
 namespace Aegilib {
 
@@ -45,6 +46,12 @@ namespace Aegilib {
 	public:
 		Time() { ms = 0; }
 		Time(int ms) { (void)ms; }
+
+		void SetMS(int milliseconds) { ms = milliseconds; }
+		int GetMS() { return ms; }
+
+		String GetString(int ms_precision,int h_precision);
+		void Parse(String data);
 	};
 
 };
diff --git a/aegilib/src/formats/format_ass.cpp b/aegilib/src/formats/format_ass.cpp
index 2b1f54f42ae25cacee88d637a6dca79d2c6949e5..ee91535c56e382a485872a95eff0739d8522d967 100644
--- a/aegilib/src/formats/format_ass.cpp
+++ b/aegilib/src/formats/format_ass.cpp
@@ -138,7 +138,8 @@ SectionEntry *FormatHandlerASS::MakeEntry(String data,String group,int version)
 			final = diag;
 
 			// Debug
-			std::cout << "[" << group.mb_str(wxConvUTF8) << "] " << diag->GetText().mb_str(wxConvUTF8) << std::endl;
+			wxString out = diag->GetStartTime().GetString(2,1) + _T(",") + diag->GetEndTime().GetString(2,1) + _T(",") + diag->GetText();
+			std::cout << out.mb_str(wxConvUTF8) << std::endl;
 		}
 
 		// Format lines
@@ -295,11 +296,11 @@ bool DialogueASS::Parse(wxString rawData, int version)
 
 	// Get start time
 	if (!tkn.HasMoreTokens()) return false;
-	start = ParseTime(tkn.GetNextToken());
+	start.Parse(tkn.GetNextToken());
 
 	// Get end time
 	if (!tkn.HasMoreTokens()) return false;
-	end = ParseTime(tkn.GetNextToken());
+	end.Parse(tkn.GetNextToken());
 
 	// Get style
 	if (!tkn.HasMoreTokens()) return false;
@@ -353,12 +354,3 @@ bool DialogueASS::Parse(wxString rawData, int version)
 
 	return true;
 }
-
-
-/////////////////////
-// Parse time string
-Time DialogueASS::ParseTime(String time)
-{
-	(void) time;
-	return 0;
-}
diff --git a/aegilib/src/formats/format_ass.h b/aegilib/src/formats/format_ass.h
index 16dac9de772178077edf2bb7bfb1e1c673a81a39..87ef15b288645ec1eb8618d5417fc247defbbe62 100644
--- a/aegilib/src/formats/format_ass.h
+++ b/aegilib/src/formats/format_ass.h
@@ -87,7 +87,6 @@ namespace Aegilib {
 		bool comment;
 
 		bool Parse(String data,int version);
-		Time ParseTime(String data);
 
 	public:
 		// Constructors
diff --git a/aegilib/src/time.cpp b/aegilib/src/time.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7cb0c3f4af6ca2417aad48b5afea5d4d5020aa1e
--- /dev/null
+++ b/aegilib/src/time.cpp
@@ -0,0 +1,109 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of the Aegisub Group nor the names of its contributors
+//     may be used to endorse or promote products derived from this software
+//     without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB/AEGILIB
+//
+// Website: http://www.aegisub.net
+// Contact: mailto:amz@aegisub.net
+//
+
+#include "aegilib.h"
+using namespace Aegilib;
+
+
+//////////////////////
+// Generates a string
+String Time::GetString(int ms_precision,int h_precision)
+{
+	// Enforce sanity
+	ms_precision = MID(0,ms_precision,3);
+	h_precision = MID(0,h_precision,2);
+
+	// Generate values
+	int _ms = ms;
+	int h = _ms / 3600000;
+	_ms -= h*3600000;
+	int min = _ms / 60000;
+	_ms -= min*60000;
+	int s = _ms / 1000;
+	_ms -= s*1000;
+
+	// Cap hour value
+	if (h > 9 && h_precision == 1) {
+		h = 9;
+		min = 59;
+		s = 59;
+		_ms = 999;
+	}
+
+	// Modify ms to account for precision
+	if (ms_precision == 2) _ms /= 10;
+	else if (ms_precision == 1) _ms /= 100;
+	else if (ms_precision == 0) _ms = 0;
+
+	// Generate mask string
+	wxString mask = wxString::Format(_T("%%0%ii:%%0%ii:%%0%ii.%%0%ii"),h_precision,2,2,ms_precision);
+
+	// Generate final string
+	wxString final = wxString::Format(mask,h,min,s,_ms);
+
+	// Done
+	return final;
+}
+
+
+///////////////////
+// Parses a string
+void Time::Parse(String data)
+{
+	// Break into an array of values
+	std::vector<double> values;
+	values.reserve(4);
+	size_t last = 0;
+	data += _T(":");
+	size_t len = data.Length();
+	for (size_t i=0;i<len;i++) {
+		if (data[i] == ':' || data[i] == ';') {
+			wxString temp = data.Mid(last,i-last);
+			last = i+1;
+			double tempd;
+			temp.ToDouble(&tempd);
+			values.push_back(tempd);
+		}
+	}
+
+	// Turn into milliseconds
+	ms = 0;
+	double mult = 1000.0;
+	int len2 = (int) values.size();
+	for (int i=len2;--i>=0;) {
+		ms += (int)(values[i] * mult);
+		mult *= 60.0;
+	}
+}