From 8858521436a302d366b437828128717aaa2cde57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 9 Jun 2011 20:13:00 +0200
Subject: DateTime refactoring.

Moved DateTime serializing into Base.
Fixed a bug when XEP82 dates are non-UTC.
Added unit tests.

diff --git a/3rdParty/Boost/update.sh b/3rdParty/Boost/update.sh
index 6344d72..c272d1a 100755
--- a/3rdParty/Boost/update.sh
+++ b/3rdParty/Boost/update.sh
@@ -14,6 +14,7 @@ fi
 	bind.hpp \
 	cast.hpp \
 	date_time/posix_time/posix_time.hpp \
+	date_time/local_time/local_time.hpp \
 	foreach.hpp \
 	filesystem.hpp \
 	filesystem/fstream.hpp \
diff --git a/Swiften/Base/DateTime.cpp b/Swiften/Base/DateTime.cpp
index 1120938..fae26d4 100644
--- a/Swiften/Base/DateTime.cpp
+++ b/Swiften/Base/DateTime.cpp
@@ -7,19 +7,28 @@
 #include <Swiften/Base/DateTime.h>
 
 #include <locale>
-
 #include <boost/date_time/time_facet.hpp>
+#include <boost/date_time/local_time/local_time.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
 
+#include <Swiften/Base/String.h>
+
 namespace Swift {
 
 boost::posix_time::ptime stringToDateTime(const std::string& string) {
-	static std::locale locale(std::locale::classic(), new boost::posix_time::time_input_facet("%Y-%m-%d %H:%M:%S%F%Q"));
+	static std::locale locale(std::locale::classic(), new boost::local_time::local_time_input_facet("%Y-%m-%d %H:%M:%S%F%ZP"));
 	std::istringstream stream(string); 
 	stream.imbue(locale);
-	boost::posix_time::ptime result(boost::posix_time::not_a_date_time);
+	boost::local_time::local_date_time result(boost::date_time::not_a_date_time);
 	stream >> result;
-	return result;
+	return result.utc_time();
+}
+
+std::string dateTimeToString(const boost::posix_time::ptime& time) {
+	std::string stampString = std::string(boost::posix_time::to_iso_extended_string(time));
+	String::replaceAll(stampString, ',', ".");
+	stampString += "Z";
+	return stampString;
 }
 
 }
diff --git a/Swiften/Base/DateTime.h b/Swiften/Base/DateTime.h
index 309ee56..2407ddc 100644
--- a/Swiften/Base/DateTime.h
+++ b/Swiften/Base/DateTime.h
@@ -10,8 +10,13 @@
 
 namespace Swift {
 	/**
-	 * Converts a date formatted according to XEP-0082 into a time
-	 * object.
+	 * Converts a date formatted according to XEP-0082 into a ptime
+	 * object (in UTC).
 	 */
 	boost::posix_time::ptime stringToDateTime(const std::string& string);
+
+	/**
+	 * Converts a UTC ptime object to a XEP-0082 formatted string.
+	 */
+	std::string dateTimeToString(const boost::posix_time::ptime& time);
 }
diff --git a/Swiften/Base/UnitTest/DateTimeTest.cpp b/Swiften/Base/UnitTest/DateTimeTest.cpp
new file mode 100644
index 0000000..8c3903a
--- /dev/null
+++ b/Swiften/Base/UnitTest/DateTimeTest.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <string>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <Swiften/Base/DateTime.h>
+
+using namespace Swift;
+
+class DateTimeTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(DateTimeTest);
+		CPPUNIT_TEST(testStringToDateTime_UTC);
+		CPPUNIT_TEST(testStringToDateTime_WithTimezone);
+		CPPUNIT_TEST(testDateTimeToString);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void testStringToDateTime_UTC() {
+			boost::posix_time::ptime time = stringToDateTime("1969-07-21T02:56:15Z");
+
+			CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time));
+		}
+
+		void testStringToDateTime_WithTimezone() {
+			boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00");
+
+			CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time));
+		}
+
+		void testDateTimeToString() {
+			boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00");
+
+			CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15Z"), dateTimeToString(time));
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DateTimeTest);
diff --git a/Swiften/SConscript b/Swiften/SConscript
index f196685..90be7a2 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -238,6 +238,7 @@ if env["SCONS_STAGE"] == "build" :
 			File("Avatars/UnitTest/CombinedAvatarProviderTest.cpp"),
 			File("Base/UnitTest/IDGeneratorTest.cpp"),
 			File("Base/UnitTest/StringTest.cpp"),
+			File("Base/UnitTest/DateTimeTest.cpp"),
 			File("Base/UnitTest/ByteArrayTest.cpp"),
 			File("Chat/UnitTest/ChatStateNotifierTest.cpp"),
 #		File("Chat/UnitTest/ChatStateTrackerTest.cpp"),
diff --git a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp
index 4f86faa..6148632 100644
--- a/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/DelaySerializer.cpp
@@ -11,6 +11,7 @@
 
 #include <Swiften/Base/String.h>
 #include <Swiften/Serializer/XML/XMLElement.h>
+#include <Swiften/Base/DateTime.h>
 
 namespace Swift {
 
@@ -22,16 +23,8 @@ std::string DelaySerializer::serializePayload(boost::shared_ptr<Delay> delay)  c
 	if (delay->getFrom()) {
 		delayElement.setAttribute("from", delay->getFrom()->toString());
 	}
-	std::string stampString = boostPTimeToXEP0082(delay->getStamp());
-	delayElement.setAttribute("stamp", stampString);
+	delayElement.setAttribute("stamp", dateTimeToString(delay->getStamp()));
 	return delayElement.serialize();
 }
 
-std::string DelaySerializer::boostPTimeToXEP0082(const boost::posix_time::ptime& time) {
-	std::string stampString = std::string(boost::posix_time::to_iso_extended_string(time));
-	String::replaceAll(stampString, ',', ".");
-	stampString += "Z";
-	return stampString;
-}
-
 }
diff --git a/Swiften/Serializer/PayloadSerializers/DelaySerializer.h b/Swiften/Serializer/PayloadSerializers/DelaySerializer.h
index 4705e71..06c7665 100644
--- a/Swiften/Serializer/PayloadSerializers/DelaySerializer.h
+++ b/Swiften/Serializer/PayloadSerializers/DelaySerializer.h
@@ -15,7 +15,6 @@ namespace Swift {
 			DelaySerializer();
 
 			virtual std::string serializePayload(boost::shared_ptr<Delay>)  const;
-			static std::string boostPTimeToXEP0082(const boost::posix_time::ptime& time);
 	};
 }
 
-- 
cgit v0.10.2-6-g49f6