Time: reimplementation 34/90334/9
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Thu, 22 Sep 2016 07:23:15 +0000 (09:23 +0200)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Thu, 13 Oct 2016 14:39:56 +0000 (16:39 +0200)
Reimplementation of Time class to better handle timezones
and local preferences. Time class keeps absolute time and timezone
information in order to provide localized formatting.

Change-Id: Ifc644317d633e44fffe9d275f39c835ee9b6479e

16 files changed:
clock-tests/.cproject
clock-tests/src/AlarmPresenterTestCase.cpp
clock-tests/src/TimeTest.cpp [new file with mode: 0644]
clock-tests/unittest.xml
clock/.cproject
clock/inc/Presenter/StopWatchPresenter.h
clock/inc/Utils/Time.h
clock/inc/View/TimerView.h
clock/src/Model/Alarm.cpp
clock/src/Presenter/RingPresenter.cpp
clock/src/Presenter/StopWatchPresenter.cpp
clock/src/Utils/Time.cpp
clock/src/View/AlarmView.cpp
clock/src/View/DeleteAlarmView.cpp
clock/src/View/EditAlarmView.cpp
clock/src/View/WorldClockView.cpp

index c97df95..4f14b16 100644 (file)
                                                                <option defaultValue="gnu.cpp.compiler.debugging.level.max" id="sbi.gnu.cpp.compiler.option.debugging.level.core.508515725" name="Debug level" superClass="sbi.gnu.cpp.compiler.option.debugging.level.core" valueType="enumerated"/>
                                                                <option defaultValue="false" id="sbi.gnu.cpp.compiler.option.misc.pic.core.1071875033" name="-fPIC option" superClass="sbi.gnu.cpp.compiler.option.misc.pic.core" valueType="boolean"/>
                                                                <option id="sbi.gnu.cpp.compiler.option.781067055" name="Tizen-Target" superClass="sbi.gnu.cpp.compiler.option" valueType="userObjs">
-                                                                       <listOptionValue builtIn="false" value="mobile-3.0-device.core_llvm36.armel.core.app"/>
+                                                                       <listOptionValue builtIn="false" value="mobile-3.0-emulator.core_llvm36.i386.core.app"/>
+                                                               </option>
+                                                               <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.2103208823" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${SBI_SYSROOT}/usr/include/libxml2&quot;"/>
                                                                </option>
                                                                <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.2103208823" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${SBI_SYSROOT}/usr/include/libxml2&quot;"/>
                                                                        <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
                                                                        <listOptionValue builtIn="false" value=" -fPIE"/>
                                                                        <listOptionValue builtIn="false" value="--sysroot=&quot;${SBI_SYSROOT}&quot;"/>
-                                                                       <listOptionValue builtIn="false" value="-mthumb"/>
                                                                </option>
                                                                <option id="gnu.cpp.compiler.option.include.paths.1337650806" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
                                                                <option defaultValue="gnu.c.debugging.level.max" id="sbi.gnu.c.compiler.option.debugging.level.core.1218321510" name="Debug level" superClass="sbi.gnu.c.compiler.option.debugging.level.core" valueType="enumerated"/>
                                                                <option defaultValue="false" id="sbi.gnu.c.compiler.option.misc.pic.core.824960994" name="-fPIC option" superClass="sbi.gnu.c.compiler.option.misc.pic.core" valueType="boolean"/>
                                                                <option id="sbi.gnu.c.compiler.option.1133367837" name="Tizen-Target" superClass="sbi.gnu.c.compiler.option" valueType="userObjs">
-                                                                       <listOptionValue builtIn="false" value="mobile-3.0-device.core_llvm36.armel.core.app"/>
+                                                                       <listOptionValue builtIn="false" value="mobile-3.0-emulator.core_llvm36.i386.core.app"/>
                                                                </option>
                                                                <option id="sbi.gnu.c.compiler.option.frameworks_inc.core.891354465" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.c.compiler.option.frameworks_inc.core" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${SBI_SYSROOT}/usr/include/libxml2&quot;"/>
                                                                <option id="gnu.cpp.link.option.userobjs.1206172838" name="Other objects" superClass="gnu.cpp.link.option.userobjs" valueType="userObjs">
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Common/CounterAnimator.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/MainController.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/RingController.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Alarm.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmEvent.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProvider.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProviderEvent.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProviderFile.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/StopWatch.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Timer.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/WeekFlags.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/WorldClock.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/AlarmPresenter.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/DeleteAlarmPresenter.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/EditAlarmPresenter.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/RingPresenter.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/StopWatchPresenter.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/TimerPresenter.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/BinaryFileReader.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/BinaryFileWriter.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/EventBus.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/Serialization.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/Time.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/Utils.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/AlarmView.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/CounterView.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/DeleteAlarmView.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/EditAlarmView.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/MainView.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/PageView.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/RingView.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/StopWatchView.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/TimerView.o&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/WeekFlagsView.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/View/WorldClockView.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/RingController.o&quot;"/>
                                                                        <listOptionValue builtIn="false" value="&quot;/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Timer.o&quot;"/>
                                                                        <additionalInput kind="additionalinput" paths="$(LIBS)"/>
                                                                </inputType>
                                                        </tool>
-                                                       <tool command="arm-linux-gnueabi-as" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.1231941130" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
+                                                       <tool command="i386-linux-gnueabi-as" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.1231941130" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
                                                                <inputType id="cdt.managedbuild.tool.gnu.assembler.input.834372949" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
                                                        </tool>
                                                        <tool id="org.tizen.nativecore.tool.fnmapgen.802860601" name="C FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen"/>
                                                                <option defaultValue="gnu.cpp.compiler.debugging.level.none" id="sbi.gnu.cpp.compiler.option.debugging.level.core.712308302" name="Debug level" superClass="sbi.gnu.cpp.compiler.option.debugging.level.core" valueType="enumerated"/>
                                                                <option defaultValue="false" id="sbi.gnu.cpp.compiler.option.misc.pic.core.41747109" name="-fPIC option" superClass="sbi.gnu.cpp.compiler.option.misc.pic.core" valueType="boolean"/>
                                                                <option id="sbi.gnu.cpp.compiler.option.1827232363" name="Tizen-Target" superClass="sbi.gnu.cpp.compiler.option" valueType="userObjs">
-                                                                       <listOptionValue builtIn="false" value="mobile-3.0-device.core_llvm36.armel.core.app"/>
+                                                                       <listOptionValue builtIn="false" value="mobile-3.0-emulator.core_llvm36.i386.core.app"/>
                                                                </option>
                                                                <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.971982965" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${SBI_SYSROOT}/usr/include/libxml2&quot;"/>
                                                                        <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
                                                                        <listOptionValue builtIn="false" value=" -fPIE"/>
                                                                        <listOptionValue builtIn="false" value="--sysroot=&quot;${SBI_SYSROOT}&quot;"/>
-                                                                       <listOptionValue builtIn="false" value="-mthumb"/>
                                                                </option>
                                                                <option id="gnu.cpp.compiler.option.include.paths.2079184222" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
                                                                <option defaultValue="gnu.c.debugging.level.default" id="sbi.gnu.c.compiler.option.debugging.level.core.1121232151" name="Debug level" superClass="sbi.gnu.c.compiler.option.debugging.level.core" valueType="enumerated"/>
                                                                <option defaultValue="false" id="sbi.gnu.c.compiler.option.misc.pic.core.1483125974" name="-fPIC option" superClass="sbi.gnu.c.compiler.option.misc.pic.core" valueType="boolean"/>
                                                                <option id="sbi.gnu.c.compiler.option.1432194874" name="Tizen-Target" superClass="sbi.gnu.c.compiler.option" valueType="userObjs">
-                                                                       <listOptionValue builtIn="false" value="mobile-3.0-device.core_llvm36.armel.core.app"/>
+                                                                       <listOptionValue builtIn="false" value="mobile-3.0-emulator.core_llvm36.i386.core.app"/>
                                                                </option>
                                                                <option id="sbi.gnu.c.compiler.option.frameworks_inc.core.965580502" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.c.compiler.option.frameworks_inc.core" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${SBI_SYSROOT}/usr/include/libxml2&quot;"/>
                                                                        <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
                                                                        <listOptionValue builtIn="false" value=" -fPIE"/>
                                                                        <listOptionValue builtIn="false" value="--sysroot=&quot;${SBI_SYSROOT}&quot;"/>
-                                                                       <listOptionValue builtIn="false" value="-mthumb"/>
                                                                </option>
                                                                <option id="gnu.c.compiler.option.include.paths.234793489" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
                                                                        <additionalInput kind="additionalinput" paths="$(LIBS)"/>
                                                                </inputType>
                                                        </tool>
-                                                       <tool command="arm-linux-gnueabi-as" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.1137717587" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
+                                                       <tool command="i386-linux-gnueabi-as" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.1137717587" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
                                                                <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1683314605" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
                                                        </tool>
                                                        <tool id="org.tizen.nativecore.tool.fnmapgen.940558103" name="C FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen"/>
index dd43de9..2b09b3e 100644 (file)
@@ -39,4 +39,3 @@ class TestSuite : public testing::Test
 TEST(TestSuite, test01)
 {
 }
-
diff --git a/clock-tests/src/TimeTest.cpp b/clock-tests/src/TimeTest.cpp
new file mode 100644 (file)
index 0000000..614bd06
--- /dev/null
@@ -0,0 +1,130 @@
+#include "Utils/Time.h"
+
+#include <gtest/gtest.h>
+
+using namespace testing;
+using namespace utils;
+
+class TimeTestSuite : public testing::Test
+{
+       protected:
+       // virtual void SetUp() will be called before each test is run.
+       // You should define it if you need to initialize the variables.
+       // Otherwise, you don't have to provide it.
+       virtual void SetUp()
+       {
+
+       }
+       // virtual void TearDown() will be called after each test is run.
+       // You should define it if there is cleanup work to do.
+       // Otherwise, you don't have to provide it.
+       virtual void TearDown()
+       {
+
+       }
+};
+
+// When you have a test fixture, you define a test using TEST_F.
+// Otherwise, you define a test using TEST.
+TEST(TimeTestSuite, test_default_tz)
+{
+       Time tm1(2016, 9, 17, 23, 11, 0, 0);
+       EXPECT_EQ(tm1.Format(Time::FORMAT_TIME_12H), "11:11");
+
+       Time tm2(2016, 9, 17, 23, 11, 0, 0);
+       EXPECT_EQ(tm2.Format(Time::FORMAT_TIME_24H), "23:11");
+
+       Time tm3(2016, 9, 17, 23, 11, 0, 0);
+       EXPECT_EQ(tm3.Format(Time::FORMAT_TIME_AMPM), "PM");
+
+       Time tm4(2016, 9, 17, 23, 1, 0, 0);
+       EXPECT_EQ(tm4.Format(Time::FORMAT_TIME_12H), "11:01");
+}
+
+TEST(TimeTestSuite, test_predefined_tz)
+{
+       Time tm1(2016, 9, 17, 23, 11, 0, 0, "Europe/Warsaw");
+       EXPECT_EQ(tm1.Format(Time::FORMAT_TIME_12H), "11:11");
+
+       Time tm2(2016, 9, 17, 23, 11, 0, 0, "America/New_York");
+       EXPECT_EQ(tm2.Format(Time::FORMAT_TIME_24H), "23:11");
+
+       Time tm3(2016, 9, 17, 23, 11, 0, 0, "Europe/Warsaw");
+       EXPECT_EQ(tm3.Format(Time::FORMAT_TIME_AMPM), "PM");
+
+       Time tm4(2016, 9, 17, 23, 1, 0, 0, "America/New_York");
+       EXPECT_EQ(tm4.Format(Time::FORMAT_TIME_12H), "11:01");
+}
+
+TEST(TimeTestSuite, test_tz_transform)
+{
+       Time tm1(2016, 9, 17, 8, 1, 0, 0, "Europe/Warsaw");
+       EXPECT_EQ(tm1.InTimezone("Asia/Seoul").Format(Time::FORMAT_TIME_24H), "15:01");
+       EXPECT_EQ(tm1.InTimezone("America/New_York").Format(Time::FORMAT_TIME_24H), "02:01");
+
+       Time tm2(2016, 9, 17, 4, 1, 0, 0, "Asia/Seoul");
+       EXPECT_EQ(tm2.InTimezone("Europe/Warsaw").Format(Time::FORMAT_TIME_24H), "21:01");
+       EXPECT_EQ(tm2.InTimezone("America/New_York").Format(Time::FORMAT_TIME_24H), "15:01");
+
+       Time tm3(2016, 9, 17, 4, 1, 0, 0, "Asia/Seoul");
+       EXPECT_EQ(tm3.InTimezone("Europe/Warsaw").Format(Time::FORMAT_TIME_24H), "21:01");
+       EXPECT_EQ(tm3.InTimezone("America/New_York").Format(Time::FORMAT_TIME_24H), "15:01");
+}
+
+TEST(TimeTestSuite, test_timezonebyoffset)
+{
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(0), "GMT+0:00");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(1), "GMT+0:01");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(-1), "GMT-0:01");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(-10), "GMT-0:10");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(-10), "GMT-0:10");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(-(60 * 1 + 59)), "GMT-1:59");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(60 * 1 + 59), "GMT+1:59");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(-(60 * 12 + 59)), "GMT-12:59");
+       EXPECT_EQ(Time::GetTimezoneNameByOffset(60 * 12 + 59), "GMT+12:59");
+}
+
+TEST(TimeTestSuite, test_timezonebyoffset_with_dates)
+{
+       Time tm1(2016, 9, 17, 23, 11, 0, 0, Time::GetTimezoneNameByOffset(0).c_str());
+       EXPECT_EQ(tm1.InTimezone(Time::GetTimezoneNameByOffset(0).c_str()).Format(Time::FORMAT_TIME_12H), "11:11");
+       EXPECT_EQ(tm1.InTimezone(Time::GetTimezoneNameByOffset(1).c_str()).Format(Time::FORMAT_TIME_12H), "11:12");
+       EXPECT_EQ(tm1.InTimezone(Time::GetTimezoneNameByOffset(-1).c_str()).Format(Time::FORMAT_TIME_12H), "11:10");
+       EXPECT_EQ(tm1.InTimezone(Time::GetTimezoneNameByOffset(60 * 1 + 30).c_str()).Format(Time::FORMAT_TIME_12H), "12:41");
+       EXPECT_EQ(tm1.InTimezone(Time::GetTimezoneNameByOffset(-(60 * 1 + 30)).c_str()).Format(Time::FORMAT_TIME_12H), "9:41");
+}
+
+TEST(TimeTestSuite, test_tm_conmvert)
+{
+       Time tm1(2016, 9, 17, 23, 11, 9, 0, "Europe/Warsaw");
+       auto tm = tm1.GetTMStruct();
+       EXPECT_EQ(tm.tm_year, 116);
+       EXPECT_EQ(tm.tm_mon, 8);
+       EXPECT_EQ(tm.tm_mday, 17);
+       EXPECT_EQ(tm.tm_wday, 6);
+       EXPECT_EQ(tm.tm_yday, 261);
+       EXPECT_EQ(tm.tm_hour, 23);
+       EXPECT_EQ(tm.tm_min, 11);
+       EXPECT_EQ(tm.tm_sec, 9);
+       EXPECT_TRUE(!strcmp(tm.tm_zone, "Europe/Warsaw"));
+}
+
+TEST(TimeTestSuite, test_long_format)
+{
+       Time tm1(2016, 9, 17, 23, 11, 9, 0, "Europe/Warsaw");
+       EXPECT_EQ(tm1.Format("QQQQ ? MMM d EEEE H:m:s"), "3rd quarter ? Sep 17 Saturday 23:11:9");
+}
+
+TEST(TimeTestSuite, test_long_local_format)
+{
+       Time tm1(2016, 9, 17, 23, 11, 9, 0, "Europe/Warsaw");
+       EXPECT_EQ(tm1.LocalFormat("QQQQ MMM d EEEE H:m:s"), "Saturday, Sep 17 (quarter: 3rd quarter), 23:11:09");
+}
+
+TEST(TimeTestSuite, test_format_local)
+{
+       Time tm1(2016, 9, 17, 23, 11, 0, 0,  "Europe/Warsaw");
+       EXPECT_EQ(tm1.LocalFormat("h:mm"), "11:11 PM");
+}
+
+
index 95eea85..1288f9c 100644 (file)
@@ -4,24 +4,38 @@
 <targetFile>Clock.cpp</targetFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Common/CounterAnimator.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/MainController.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/RingController.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Alarm.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmEvent.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProvider.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProviderEvent.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/AlarmProviderFile.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/StopWatch.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Timer.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/WeekFlags.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/WorldClock.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/AlarmPresenter.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/DeleteAlarmPresenter.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/EditAlarmPresenter.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/RingPresenter.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/StopWatchPresenter.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Presenter/TimerPresenter.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/BinaryFileReader.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/BinaryFileWriter.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/EventBus.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/Serialization.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/Time.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Utils/Utils.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/AlarmView.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/CounterView.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/DeleteAlarmView.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/EditAlarmView.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/MainView.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/PageView.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/RingView.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/StopWatchView.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/TimerView.o</targetObjectFile>
+<targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/WeekFlagsView.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/View/WorldClockView.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Controller/RingController.o</targetObjectFile>
 <targetObjectFile>/home/l.stanislaws/Projects/clock/clock/Debug/src/Model/Timer.o</targetObjectFile>
index 8fe819a..318caca 100644 (file)
@@ -27,7 +27,7 @@
                                                                <option defaultValue="gnu.cpp.compiler.debugging.level.max" id="sbi.gnu.cpp.compiler.option.debugging.level.core.560740604" name="Debug level" superClass="sbi.gnu.cpp.compiler.option.debugging.level.core" valueType="enumerated"/>
                                                                <option defaultValue="false" id="sbi.gnu.cpp.compiler.option.misc.pic.core.1289916342" name="-fPIC option" superClass="sbi.gnu.cpp.compiler.option.misc.pic.core" valueType="boolean"/>
                                                                <option id="sbi.gnu.cpp.compiler.option.1180801303" name="Tizen-Target" superClass="sbi.gnu.cpp.compiler.option" valueType="userObjs">
-                                                                       <listOptionValue builtIn="false" value="mobile-3.0-device.core_llvm36.armel.core.app"/>
+                                                                       <listOptionValue builtIn="false" value="mobile-3.0-emulator.core_llvm36.i386.core.app"/>
                                                                </option>
                                                                <option id="sbi.gnu.cpp.compiler.option.frameworks_inc.core.728385348" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.cpp.compiler.option.frameworks_inc.core" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${SBI_SYSROOT}/usr/include/libxml2&quot;"/>
                                                                        <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
                                                                        <listOptionValue builtIn="false" value=" -fPIE"/>
                                                                        <listOptionValue builtIn="false" value="--sysroot=&quot;${SBI_SYSROOT}&quot;"/>
-                                                                       <listOptionValue builtIn="false" value="-mthumb"/>
                                                                </option>
                                                                <option id="gnu.cpp.compiler.option.include.paths.1668895094" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
                                                                <option defaultValue="gnu.c.debugging.level.max" id="sbi.gnu.c.compiler.option.debugging.level.core.1101789042" name="Debug level" superClass="sbi.gnu.c.compiler.option.debugging.level.core" valueType="enumerated"/>
                                                                <option defaultValue="false" id="sbi.gnu.c.compiler.option.misc.pic.core.207975531" name="-fPIC option" superClass="sbi.gnu.c.compiler.option.misc.pic.core" valueType="boolean"/>
                                                                <option id="sbi.gnu.c.compiler.option.600001807" name="Tizen-Target" superClass="sbi.gnu.c.compiler.option" valueType="userObjs">
-                                                                       <listOptionValue builtIn="false" value="mobile-3.0-device.core_llvm36.armel.core.app"/>
+                                                                       <listOptionValue builtIn="false" value="mobile-3.0-emulator.core_llvm36.i386.core.app"/>
                                                                </option>
                                                                <option id="sbi.gnu.c.compiler.option.frameworks_inc.core.2111102001" name="Tizen-Frameworks-Include-Path" superClass="sbi.gnu.c.compiler.option.frameworks_inc.core" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${SBI_SYSROOT}/usr/include/libxml2&quot;"/>
                                                                        <listOptionValue builtIn="false" value="${RS_COMPILER_MISC}"/>
                                                                        <listOptionValue builtIn="false" value=" -fPIE"/>
                                                                        <listOptionValue builtIn="false" value="--sysroot=&quot;${SBI_SYSROOT}&quot;"/>
-                                                                       <listOptionValue builtIn="false" value="-mthumb"/>
                                                                </option>
                                                                <option id="gnu.c.compiler.option.include.paths.2001094680" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
                                                                        <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/inc}&quot;"/>
                                                                        <additionalInput kind="additionalinput" paths="$(LIBS)"/>
                                                                </inputType>
                                                        </tool>
-                                                       <tool command="arm-linux-gnueabi-as" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.784950171" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
+                                                       <tool command="i386-linux-gnueabi-as" id="org.tizen.nativeapp.tool.sbi.gnu.assembler.base.784950171" name="Assembler" superClass="org.tizen.nativeapp.tool.sbi.gnu.assembler.base">
                                                                <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1097107177" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
                                                        </tool>
                                                        <tool id="org.tizen.nativecore.tool.fnmapgen.1050341554" name="C FN-Map Generator" superClass="org.tizen.nativecore.tool.fnmapgen"/>
index 9ce0c45..d3302f0 100644 (file)
@@ -25,7 +25,6 @@
 #include "View/View.h"
 #include "Model/StopWatch.h"
 #include "Common/CounterAnimator.h"
-#include "Utils/Time.h"
 
 namespace presenter {
 
@@ -38,6 +37,9 @@ namespace presenter {
                view::StopWatchView *ui_;
                model::StopWatch *model_;
 
+               struct Time {
+                       unsigned int Hour, Min, Sec, Msec;
+               };
                common::CounterAnimator animator_;
 
                void StartButtonClicked(void);
@@ -48,7 +50,7 @@ namespace presenter {
                void TimeUpdateRequest(void);
 
                std::string GetTimeString(std::chrono::milliseconds time);
-               utils::Time GetTimeStructure(std::chrono::milliseconds time);
+               Time GetTimeStructure(std::chrono::milliseconds time);
        };
 }
 
index 14c4323..f27442c 100644 (file)
 #include "Common/Defines.h"
 #include "Utils/Serialization.h"
 
+#include <map>
+#include <ctime>
+#include <utils_i18n.h>
+
 namespace utils {
-       enum Format {
-               FORMAT_12H,
-               FORMAT_24H
-       };
        class Time : public utils::ISerializable {
                public:
-                       unsigned int Hour, Min, Sec, Msec;
-                       Time() : Hour(0), Min(0), Sec(0) , Msec(0) {}
-                       Time(unsigned int h, unsigned int m, unsigned int s, unsigned int ms = 0) : Hour(h), Min(m), Sec(s), Msec(ms) {}
+                       /** Predefined formats for convenience */
+                       static const char *FORMAT_TIME_12H;// = "h:mm";
+                       static const char *FORMAT_TIME_24H; // = "HH:mm";
+                       static const char *FORMAT_TIME_AMPM; // = "a";
+
+                       enum class Month {
+                               January   = I18N_UCALENDAR_JANUARY,
+                               Febuary   = I18N_UCALENDAR_FEBRUARY,
+                               March     = I18N_UCALENDAR_MARCH,
+                               April     = I18N_UCALENDAR_APRIL,
+                               May       = I18N_UCALENDAR_MAY,
+                               June      = I18N_UCALENDAR_JUNE,
+                               July      = I18N_UCALENDAR_JULY,
+                               August    = I18N_UCALENDAR_AUGUST,
+                               September = I18N_UCALENDAR_SEPTEMBER,
+                               October   = I18N_UCALENDAR_OCTOBER,
+                               November  = I18N_UCALENDAR_NOVEMBER,
+                               December  = I18N_UCALENDAR_DECEMBER,
+                       };
+
+                       Time() : timezone_(GetCurrentTimezone()), milliseconds_(0) {}
+
+                       /**
+                        * @brief copy constructor
+                        */
+                       Time(const Time &tm);
+
+                       /**
+                        * @brief Creates new Time in given timezone
+                        *
+                        * @note if timezone parameter is null, the local timezone will be
+                        * used instead.
+                        */
+                       Time(unsigned int year, Month month, unsigned int day,
+                                       unsigned int hour, unsigned int minute, unsigned int seconds,
+                                       unsigned int miliseconds, const char *timezone = nullptr);
+
+                       /**
+                        * @brief Deserialization constructor
+                        */
                        Time(utils::IReader &);
+
+                       /**
+                        * @brief Serialization constructor
+                        */
                        void Serialize(utils::IWriter &w) const;
-                       inline bool operator==(const Time &a) { return (a.Hour == Hour ) &&
-                               (a.Min == Min) && (a.Sec == Sec) && (a.Msec == Msec); }
-                       std::string Format(enum Format format) const;
-                       std::string Meridiem() const;
-                       std::string GetMeridiemByOffset(int timezone_offset) const;
-                       std::string GetFormattedTime(const char *icu_format) const;
-                       std::string GetFormattedTimeByTimezoneOffset(const char *icu_format, int timezone_offset) const;
-                       int GetLocalTimezoneOffset(void) const;
-                       const std::string GetTimezoneRelativeToLocalString(int timezone_offset);
-                       std::string GetTimezoneDate(int timezone_offset);
-
-                       std::string GetDate() const;
 
+                       /**
+                        * @brief Compare operator
+                        */
+                       bool operator==(const Time &a);
+
+                       /**
+                        * @brief Return year AD.
+                        */
+                       unsigned int GetYear() const;
+
+                       /**
+                        * @brief Return month
+                        */
+                       Month GetMonth() const;
+
+                       /**
+                        * @brief Return a number of day in given month [1-31]
+                        */
+                       unsigned int GetDay() const;
+
+                       /**
+                        * @brief Return hour [0-23]
+                        */
+                       unsigned int GetHour() const;
+
+                       /**
+                        * @brief Return minute [0-59]
+                        */
+                       unsigned int GetMinute() const;
+
+                       /**
+                        * @brief Return second [0-59]
+                        */
+                       unsigned int GetSecond() const;
+
+                       /**
+                        * @brief Return milliseconds [0-999]
+                        */
+                       unsigned int GetMilliSec() const;
+
+                       /**
+                        * @brief Returns textual representation of time.
+                        *
+                        * @param format i18n valid format. Please refer to Tizen utils_i18n.h
+                        * documentation formats for reference.
+                        *
+                        * example: "HH:mm", "h:mm a"
+                        */
+                       std::string Format(const char *format) const;
+
+                       /**
+                        * @brief Returns textual representation of time adjusted to local
+                        * preferences.
+                        *
+                        * @param format i18n valid format. Please refer to Tizen utils_i18n.h
+                        * documentation formats for reference.
+                        *
+                        * @note It is guaranteed that textual representation will contain
+                        * all fields specified in format parameter. Some additional fields
+                        * may be appended according to local preferences.
+                        */
+                       std::string LocalFormat(const char *format) const;
+
+                       /**
+                        * Return current local time
+                        */
                        static Time Now(void);
+
+                       /**
+                        * @brief Returns Time adjusted to localtime.
+                        */
+                       Time Local() const;
+
+                       /**
+                        * @brief Returns Time adjusted to given timezone.
+                        *
+                        * @param timezone valid i18n timezone string.
+                        */
+                       Time InTimezone(const char *timezone) const;
+
+                       /**
+                        * @brief Converts time to tm struct
+                        *
+                        * @note returned tm_zone remains valid until Time object is
+                        * destroyed.
+                        */
+                       std::tm GetTmStruct() const;
+
+                       /**
+                        * @brief Return timezone in "GMT+1:00" format according to
+                        * given offset
+                        *
+                        * @param[in] offset timezone offset in minutes.
+                        */
+                       static std::string GetTimezoneNameByOffset(int offset);
+
+                       /**
+                        * @brief Return timezone offset.
+                        *
+                        * @param[in] timezone valid timezone id.
+                        *
+                        * @ret difference in minutes between "timezone" and GMT:+00
+                        * @note return INT_MAX when timezone string is invalid.
+                        */
+                       static int GetTimezoneOffset(const char *timezone);
+
+                       /**
+                        * @brief Get current timezone
+                        */
+                       static const std::string &GetCurrentTimezone();
+
+               private:
+                       Time(double milliseconds, const std::string &tz);
+
+                       std::string timezone_;
+                       double milliseconds_;
+
+                       static const char *GetLocale();
+                       static std::map<std::string, std::string> best_patterns_cache;
+                       static std::string FormatInternal(double time, const std::string &timezone,
+                                       const char *locale, const char *pattern, size_t buf_len = 32);
+                       static const std::string *GetBestPattern(const char *locale,
+                                       const char *skeleton);
+                       static std::string GenerateBestPattern(const char *locale,
+                                       const char *skeleton, unsigned int m = 2);
        };
 } /* utils */
 
index 1291652..4ee2adb 100644 (file)
@@ -26,7 +26,6 @@
 #include "View/View.h"
 #include "View/PageView.h"
 #include "View/CounterView.h"
-#include "Utils/Time.h"
 
 namespace view {
 
@@ -79,7 +78,11 @@ namespace view {
                Evas_Object *selector_ = NULL;
                view::CounterView *counter_ = NULL;
 
-               utils::Time set_time_;
+               struct Time {
+                       Time() : Hour(0), Min(0), Sec(0) {}
+                       unsigned int Hour, Min, Sec;
+               };
+               Time set_time_;
 
                std::vector<std::function<void(void)>> signals
                        = std::vector<std::function<void(void)>>((int)TimerSignal::MAX, nullptr);
index 6582e2f..03c87b6 100644 (file)
@@ -48,27 +48,17 @@ Alarm::Alarm() :
 void Alarm::Activate()
 {
        int err;
-       struct tm tmtime = {0, };
+       struct tm tmtime = time.GetTmStruct();
 
        if (activated)
                return;
 
-       err = alarm_get_current_time(&tmtime);
-       if (err != ALARM_ERROR_NONE) {
-               ERR("alarm_get_current_time failed: %s", get_error_message(err));
-               return;
-       }
-
        app_control_h control = AppControlCreate();
        if (!control) {
                DBG("AppControlCreate failed");
                return;
        }
 
-       tmtime.tm_hour = time.Hour;
-       tmtime.tm_min= time.Min;
-       tmtime.tm_sec= time.Sec;
-
        err = alarm_schedule_with_recurrence_week_flag(
                        control,
                        &tmtime,
index 2a72e5e..569d4f7 100644 (file)
@@ -60,8 +60,10 @@ RingPresenter::RingPresenter(view::RingView *view, model::Alarm *alarm)
 
        utils::Time time = alarm_->GetTime();
 
-       view_->SetTitle(alarm_->GetName().c_str());
-       view_->SetTimeLabel(time.Meridiem().c_str(), time.GetFormattedTime("HH:mm").c_str(), time.GetDate().c_str());
+       view->SetTitle(alarm->GetName().c_str());
+       view->SetTimeLabel(time.Format(utils::Time::FORMAT_TIME_AMPM).c_str(),
+                       time.Format(utils::Time::FORMAT_TIME_12H).c_str(),
+                       time.Format("E, d MMMM").c_str());
        if (utils::Utils::FileExists(alarm_->GetMelody().c_str()))
                view_->PlayMusic(alarm_->GetMelody().c_str(), alarm_->GetVolume());
        else {
index 8c2d944..9fd7230 100644 (file)
@@ -130,7 +130,7 @@ void StopWatchPresenter::TimeUpdateRequest()
 {
        milliseconds time = model_->GetTime();
 
-       utils::Time ts = GetTimeStructure(time);
+       Time ts = GetTimeStructure(time);
        ui_->DisplayTime(ts.Hour, ts.Min, ts.Sec, ts.Msec);
 
        const model::Lap *last = model_->GetLastLap();
@@ -142,9 +142,9 @@ void StopWatchPresenter::TimeUpdateRequest()
        ui_->DisplayLapTime(ts.Hour, ts.Min, ts.Sec, ts.Msec);
 }
 
-utils::Time StopWatchPresenter::GetTimeStructure(milliseconds time)
+StopWatchPresenter::Time StopWatchPresenter::GetTimeStructure(milliseconds time)
 {
-       utils::Time ts;
+       Time ts;
 
        ts.Hour = duration_cast<hours>(time).count() % 100;
        ts.Min = duration_cast<minutes>(time).count() % 60;
index 1583779..cfb03c4 100644 (file)
 #include "Utils/Time.h"
 #include "Utils/Log.h"
 
-#include <utils_i18n.h>
 #include <cstring>
 #include <ctime>
 #include <Elementary.h>
+#include <system_settings.h>
+
 
 using namespace utils;
 
+
+const char *Time::FORMAT_TIME_12H = "h:mm";
+const char *Time::FORMAT_TIME_24H = "HH:mm";
+const char *Time::FORMAT_TIME_AMPM = "a";
+const int BEST_PATTERNS_CACHE_MAX_CAPACITY = 10;
+
+std::map<std::string, std::string> Time::best_patterns_cache;
+
+
 Time::Time(utils::IReader &r)
 {
-       utils::Deserialize(r, Hour);
-       utils::Deserialize(r, Min);
-       utils::Deserialize(r, Sec);
-       utils::Deserialize(r, Msec);
+       utils::Deserialize(r, timezone_);
+       utils::Deserialize(r, milliseconds_);
 }
 
 void Time::Serialize(utils::IWriter &w) const
 {
-       utils::Serialize(w, Hour);
-       utils::Serialize(w, Min);
-       utils::Serialize(w, Sec);
-       utils::Serialize(w, Msec);
+       utils::Serialize(w, timezone_);
+       utils::Serialize(w, milliseconds_);
+}
+
+// Simple wrapper around i18n_uchar strings to simplify i18n_uchar strings
+// management
+class I18nString {
+       public:
+               I18nString(const char *str = nullptr);
+               I18nString(const std::string &str);
+               ~I18nString();
+               void reserve(size_t max_characters);
+               const i18n_uchar *i18n_str() const { return data_;}
+               std::string std_string() const;
+               i18n_uchar& operator[](int index);
+               size_t size() const { return size_;}
+       private:
+               i18n_uchar *data_;
+               size_t size_;
+};
+
+I18nString::I18nString(const char *str)
+{
+       str = str ? str : "";
+       size_ = strlen(str);
+       data_ = new i18n_uchar[size_ + 1];
+       i18n_ustring_copy_ua_n(data_, str, size_ + 1);
+       if (get_last_result() != I18N_ERROR_NONE) {
+               FAT("i18n_ustring_copy_ua_n failed");
+       }
+}
+
+i18n_uchar& I18nString::operator[](int index)
+{
+       return data_[index];
+}
+
+I18nString::I18nString(const std::string &str)
+{
+       size_ = str.size();
+       data_ = new i18n_uchar[size_ + 1];
+       i18n_ustring_copy_ua_n(data_, str.c_str(), size_ + 1);
+       if (get_last_result() != I18N_ERROR_NONE) {
+               FAT("i18n_ustring_copy_ua_n failed");
+       }
+}
+
+void I18nString::reserve(size_t max_characters)
+{
+       size_ = max_characters;
+       delete[] data_;
+       data_ = new i18n_uchar[size_ + 1]();
+}
+
+I18nString::~I18nString()
+{
+       delete[] data_;
+}
+
+std::string I18nString::std_string() const
+{
+       std::string str;
+       size_t new_size = i18n_ustring_get_length(data_);
+       if (get_last_result() != I18N_ERROR_NONE) {
+               FAT("i18n_ustring_copy_ua_n failed");
+       }
+       str.reserve(new_size + 1);
+       str.resize(new_size);
+       i18n_ustring_copy_au(&str[0], data_);
+       if (get_last_result() != I18N_ERROR_NONE) {
+               FAT("i18n_ustring_copy_ua_n failed");
+       }
+       return str;
+}
+
+/**
+ * @locale -> can be NULL
+ * @skeleton -> cannot be NULL
+ */
+std::string Time::GenerateBestPattern(const char *locale, const char *skeleton, unsigned int multip)
+{
+       i18n_udatepg_h generator;
+       I18nString u_best_pattern;
+       I18nString u_skeleton(skeleton);
+       int32_t best_pattern_len;
+
+       // estimate required output lenght - should be enough in 99% cases
+       u_best_pattern.reserve(u_skeleton.size() * multip);
+
+       int err = i18n_udatepg_create(NULL, &generator);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_udatepg_create failed: %s", get_error_message(err));
+               return "";
+       }
+
+       err = i18n_udatepg_get_best_pattern(generator, u_skeleton.i18n_str(),
+                       u_skeleton.size(), &u_best_pattern[0], u_best_pattern.size(), &best_pattern_len);
+       if (err == I18N_ERROR_BUFFER_OVERFLOW) {
+               INF("Best pattern too long: %s. Retrying with longer buffer...", skeleton);
+               i18n_udatepg_destroy(generator);
+               return GenerateBestPattern(locale, skeleton, multip + 1);
+       } else if (err != I18N_ERROR_NONE) {
+               ERR("i18n_udatepg_get_best_pattern failed[%d]: %s", err, get_error_message(err));
+               i18n_udatepg_destroy(generator);
+               return "";
+       }
+
+       i18n_udatepg_destroy(generator);
+       return u_best_pattern.std_string();
 }
 
-std::string Time::Format(enum Format format) const
+/**
+ * Gets best pattern for given locale, containing all fields specified in skeleton
+ */
+const std::string *Time::GetBestPattern(const char *locale, const char *skeleton)
 {
-       switch (format) {
-               case FORMAT_12H:
-                       return GetFormattedTime("h:mm");
-               case FORMAT_24H:
-                       return GetFormattedTime("HH:mm");
+       // use small cache to speed up matching patterns
+       auto it = best_patterns_cache.find(skeleton);
+
+       if (it != best_patterns_cache.end()) {
+               return &(it->second);
+       }
+
+       // if not found generate new localized pattern using i18n
+       std::string best_pattern = GenerateBestPattern(locale, skeleton);
+       if (best_pattern == "") {
+               ERR("Unable to generate localized format pattern for '%s'", skeleton);
+               return nullptr;
        }
-       abort();
-       return "";
+
+       // clear cache if exceeded max capacity
+       if (best_patterns_cache.size() > BEST_PATTERNS_CACHE_MAX_CAPACITY)
+               best_patterns_cache.clear();
+
+       auto it2 = best_patterns_cache.insert(std::pair<std::string, std::string>(skeleton, best_pattern));
+
+       return &(it2.first->second);
 }
 
-std::string Time::Meridiem() const
+std::string Time::LocalFormat(const char *format) const
 {
-       return Hour >= 12 ? "PM" : "AM";
+       if (!format) return "";
+
+       const std::string *pattern = GetBestPattern(GetLocale(), format);
+       if (!pattern) {
+               ERR("Unable to get localized format.");
+               return "";
+       }
+       return FormatInternal(milliseconds_, timezone_, GetLocale(), pattern->c_str());
 }
 
-std::string Time::GetMeridiemByOffset(int timezone_offset) const
+std::string Time::Format(const char *format) const
 {
-       return "PM";
+       if (!format) return "";
+       return FormatInternal(milliseconds_, timezone_, GetLocale(), format);
 }
 
-std::string Time::GetFormattedTime(const char *icu_format) const
+std::string Time::FormatInternal(double time, const std::string &timezone,
+               const char *locale, const char *pattern, size_t buf_len)
 {
-       char buf[32] = {0,};
-       if (!strcmp(icu_format, "HH:mm")) {
-               snprintf(buf, sizeof(buf), "%d:%d", Hour, Min);
+       i18n_udate_format_h formatter;
+       I18nString u_timezone(timezone);
+       I18nString u_pattern(pattern);
+       I18nString u_formatted;
+       i18n_udate u_date = (i18n_udate)time;
+       int32_t formatted_size_needed;
+
+       int err = i18n_udate_create(I18N_UDATE_PATTERN, I18N_UDATE_PATTERN, locale,
+                       u_timezone.i18n_str(), -1, u_pattern.i18n_str(), -1, &formatter);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_udate_create failed: %s", get_error_message(err));
+               return "";
        }
-       if (!strcmp(icu_format, "h:mm")) {
-               snprintf(buf, sizeof(buf), "%d:%d", Hour > 12 ? Hour - 12 : Hour, Min);
+
+       u_formatted.reserve(buf_len);
+
+       err = i18n_udate_format_date(formatter, u_date, &u_formatted[0], u_formatted.size(),
+                       nullptr, &formatted_size_needed);
+       if (err == I18N_ERROR_BUFFER_OVERFLOW) {
+               INF("Buffer not sufficient. Retrying with bigger buffer...");
+               i18n_udate_destroy(formatter);
+               return FormatInternal(time, timezone, locale, pattern, buf_len * 2);
+       } else if (err != I18N_ERROR_NONE) {
+               ERR("i18n_udate_format_date failed: %s", get_error_message(err));
+               i18n_udate_destroy(formatter);
+               return "";
        }
-       return buf;
+
+       i18n_udate_destroy(formatter);
+       return u_formatted.std_string();
 }
 
-std::string Time::GetFormattedTimeByTimezoneOffset(const char *icu_format, int timezone_offset) const
+Time::Time(unsigned int year, Month month, unsigned int day,
+               unsigned int hour, unsigned int minute, unsigned int seconds,
+               unsigned int miliseconds, const char *timezone)
 {
-       return "15:01";
+       i18n_ucalendar_h calendar;
+       i18n_udate udate;
+
+       if (!timezone)
+               timezone_ = GetCurrentTimezone();
+       else
+               timezone_ = timezone;
+
+       I18nString u_timezone(timezone_);
+
+       int err = i18n_ucalendar_create(u_timezone.i18n_str(), -1, nullptr,
+                       I18N_UCALENDAR_GREGORIAN, &calendar);
+       if (err != I18N_ERROR_NONE) {
+               FAT("i18n_ucalendar_create failed[%d]: %s", err, get_error_message(err));
+       }
+
+       err = i18n_ucalendar_set_date_time(calendar,
+                       year, (int)month, day, hour, minute, seconds);
+       if (err != I18N_ERROR_NONE) {
+               i18n_ucalendar_destroy(calendar);
+               FAT("i18n_ucalendar_set_date_time failed[%d]: %s", err, get_error_message(err));
+       }
+
+       err = i18n_ucalendar_get_milliseconds(calendar, &udate);
+       if (err != I18N_ERROR_NONE) {
+               i18n_ucalendar_destroy(calendar);
+               FAT("i18n_ucalendaer_get_miliseconds failed[%d]: %s", err, get_error_message(err));
+       }
+
+       milliseconds_ = udate;
+       i18n_ucalendar_destroy(calendar);
 }
 
-int Time::GetLocalTimezoneOffset(void) const
+bool Time::operator==(const Time &a)
 {
-       return 60;
+       return a.milliseconds_ == milliseconds_;
 }
 
-const std::string Time::GetTimezoneRelativeToLocalString(int timezone_offset)
+Time Time::Now(void)
 {
-       char *pattern;
-       static char relative[128] = { 0, };
-       std::string s;
+       i18n_udate handle;
+
+       int err = i18n_ucalendar_get_now(&handle);
+       if (err != I18N_ERROR_NONE) {
+               FAT("i18n_ucalendar_get_now failed[%d]: %s", err, get_error_message(err));
+       }
 
-       int local_timezone_offset = GetLocalTimezoneOffset();
-       int offset_integer = (abs(timezone_offset - local_timezone_offset)) / 60;
-       int offset_remainder = (abs(timezone_offset - local_timezone_offset)) % 60;
+       return Time(double(handle), GetCurrentTimezone());
+}
 
-       DBG("passed offset:%d, local:%d, remainder:%d", timezone_offset,
-               local_timezone_offset, offset_remainder);
+const char *Time::GetLocale()
+{
+       static const char *locale;
 
-       if (timezone_offset < local_timezone_offset) {
-               if (offset_remainder > 0) {
-                       pattern = _("IDS_CLOCK_BODY_PS1D_H_P2SD_M_BEHIND_ABB");
-                       snprintf(relative, sizeof(relative), pattern, offset_integer,
-                               offset_remainder);
+       if (!locale) {
+               char *l;
+               int ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &l);
+               if (ret != SYSTEM_SETTINGS_ERROR_NONE) {
+                       ERR("system_settings_get_value_string failed: %s", get_error_message(ret));
+                       locale = getenv("LOCALE") ? strdup(getenv("LOCALE")) : "";
                } else {
-                       pattern = _("IDS_CLOCK_BODY_PD_H_BEHIND_ABB");
-                       snprintf(relative, sizeof(relative), pattern, offset_integer);
+                       locale = l;
                }
+               if (!locale)
+                       FAT("Unable to get current locale.");
+       }
+       return locale;
+}
 
-       } else if (timezone_offset > local_timezone_offset) {
-               if (offset_remainder > 0) {
-                       pattern = _("IDS_CLOCK_BODY_PS1D_H_P2SD_M_AHEAD_ABB");
-                       snprintf(relative, sizeof(relative), pattern, offset_integer,
-                               offset_remainder);
-               } else {
-                       pattern = _("IDS_CLOCK_BODY_PD_H_AHEAD_ABB");
-                       snprintf(relative, sizeof(relative), pattern, offset_integer);
+Time Time::Local() const
+{
+       return Time(milliseconds_, GetCurrentTimezone());
+}
+
+Time Time::InTimezone(const char *timezone) const
+{
+       return Time(milliseconds_, timezone);
+}
+
+const std::string& Time::GetCurrentTimezone()
+{
+       static std::string timezone;
+
+       if (timezone.empty()) {
+               i18n_timezone_h handle;
+               char *timezone_str;
+               int err = i18n_timezone_create_default(&handle);
+               if (err != I18N_ERROR_NONE) {
+                       FAT("i18n_timezone_create_default failed: %s", get_error_message(err));
                }
+               err = i18n_timezone_get_id(handle, &timezone_str);
+               if (err != I18N_ERROR_NONE) {
+                       i18n_timezone_destroy(handle);
+                       FAT("i18n_timezone_get_id failed: %s", get_error_message(err));
+               }
+               i18n_timezone_destroy(handle);
+               timezone = std::string(timezone_str);
+               free(timezone_str);
+       }
+       return timezone;
+}
+
+Time::Time(double milliseconds, const std::string &tz)
+{
+       timezone_ = tz;
+       milliseconds_ = milliseconds;
+}
 
-       } else {
-               snprintf(relative, sizeof(relative), "Same as local time");
+std::string Time::GetTimezoneNameByOffset(int offset)
+{
+       char buf[16];
+       char sign = offset >= 0 ? '+' : '-';
+
+       int hours = abs(offset) / 60;
+       int minutes = abs(offset) % 60;
+
+       snprintf(buf, sizeof(buf), "GMT%c%d:%02d", sign, hours, minutes);
+       return std::string(buf);
+}
+
+static int GetCalendarField(double milliseconds, const char *zone, const char *locale,
+               i18n_ucalendar_date_fields_e field)
+{
+       i18n_ucalendar_h calendar;
+       I18nString u_zone(zone);
+       int32_t value;
+
+       int err = i18n_ucalendar_create(u_zone.i18n_str(), -1, locale,
+                       I18N_UCALENDAR_GREGORIAN, &calendar);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_ucalendar_create failed: %s", get_error_message(err));
+               return -1;
+       }
+
+       err = i18n_ucalendar_set_milliseconds(calendar, (i18n_udate)milliseconds);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_ucalendar_set_milliseconds failed: %s", get_error_message(err));
+               i18n_ucalendar_destroy(calendar);
+               return -1;
+       }
+
+       err = i18n_ucalendar_get(calendar, field, &value);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_ucalendar_get failed: (%d) %s", field, get_error_message(err));
+               i18n_ucalendar_destroy(calendar);
+               return -1;
        }
-       return &relative[0];
+
+       i18n_ucalendar_destroy(calendar);
+       return value;
+}
+
+unsigned int Time::GetYear() const
+{
+       return GetCalendarField(milliseconds_, timezone_.c_str(), GetLocale(), I18N_UCALENDAR_YEAR);
+}
+
+Time::Month Time::GetMonth() const
+{
+       return (Time::Month)GetCalendarField(milliseconds_, timezone_.c_str(), GetLocale(), I18N_UCALENDAR_MONTH);
+}
+
+unsigned int Time::GetDay() const
+{
+       return GetCalendarField(milliseconds_, timezone_.c_str(), GetLocale(), I18N_UCALENDAR_DAY_OF_MONTH);
+}
+
+unsigned int Time::GetHour() const
+{
+       return GetCalendarField(milliseconds_, timezone_.c_str(), GetLocale(), I18N_UCALENDAR_HOUR_OF_DAY);
+}
+
+unsigned int Time::GetMinute() const
+{
+       return GetCalendarField(milliseconds_, timezone_.c_str(), GetLocale(), I18N_UCALENDAR_MINUTE);
+}
+
+unsigned int Time::GetSecond() const
+{
+       return GetCalendarField(milliseconds_, timezone_.c_str(), GetLocale(), I18N_UCALENDAR_SECOND);
+}
+
+unsigned int Time::GetMilliSec() const
+{
+       return int(milliseconds_) % 1000;
 }
 
-std::string Time::GetTimezoneDate(int timezone_offset)
+static int i18n_calendar_month_2_tm_month(int icu_month)
 {
-       return "Mon 32 Aug";
+       switch (icu_month) {
+               case I18N_UCALENDAR_JANUARY:
+                       return 0;
+               case I18N_UCALENDAR_FEBRUARY:
+                       return 1;
+               case I18N_UCALENDAR_MARCH:
+                       return 2;
+               case I18N_UCALENDAR_APRIL:
+                       return 3;
+               case I18N_UCALENDAR_MAY:
+                       return 4;
+               case I18N_UCALENDAR_JUNE:
+                       return 5;
+               case I18N_UCALENDAR_JULY:
+                       return 6;
+               case I18N_UCALENDAR_AUGUST:
+                       return 7;
+               case I18N_UCALENDAR_SEPTEMBER:
+                       return 8;
+               case I18N_UCALENDAR_OCTOBER:
+                       return 9;
+               case I18N_UCALENDAR_NOVEMBER:
+                       return 10;
+               case I18N_UCALENDAR_DECEMBER:
+                       return 11;
+       }
+       FAT("Invalid month constant.");
+       return -1;
 }
 
-std::string Time::GetDate() const
+std::tm Time::GetTmStruct() const
 {
-       time_t now;
-       time(&now);
+       std::tm tmstruct = {0,};
+       i18n_ucalendar_h calendar;
+       I18nString u_zone(timezone_);
+       int32_t value;
+
+       int err = i18n_ucalendar_create(u_zone.i18n_str(), -1, GetLocale(),
+                       I18N_UCALENDAR_GREGORIAN, &calendar);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_ucalendar_create failed: %s", get_error_message(err));
+               return tmstruct;
+       }
+
+       err = i18n_ucalendar_set_milliseconds(calendar, (i18n_udate)milliseconds_);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_ucalendar_set_milliseconds failed: %s", get_error_message(err));
+               i18n_ucalendar_destroy(calendar);
+               return tmstruct;
+       }
+
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_YEAR, &value);
+       tmstruct.tm_year = value - 1900;
+
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_MONTH, &value);
+       tmstruct.tm_mon = i18n_calendar_month_2_tm_month(value);
 
-       struct timeval *day;
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_DAY_OF_MONTH, &value);
+       tmstruct.tm_mday = value;
 
-       struct tm *timeInfo = localtime(&now);
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_HOUR_OF_DAY, &value);
+       tmstruct.tm_hour = value;
 
-       char buffer[128] = {0, };
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_MINUTE, &value);
+       tmstruct.tm_min = value;
 
-       std::strftime(buffer, sizeof(buffer)/sizeof(buffer[0]), "%a, %e %B", timeInfo);
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_SECOND, &value);
+       tmstruct.tm_sec = value;
 
-       return std::string(buffer);
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_DAY_OF_WEEK, &value);
+       tmstruct.tm_wday = value - 1;
+
+       i18n_ucalendar_get(calendar, I18N_UCALENDAR_DAY_OF_YEAR, &value);
+       tmstruct.tm_yday = value - 1;
+
+       tmstruct.tm_zone = timezone_.c_str();
+       tmstruct.tm_gmtoff = GetTimezoneOffset(timezone_.c_str()) * 60;
+
+       i18n_ucalendar_destroy(calendar);
+       return tmstruct;
 }
 
-Time Time::Now(void)
+Time::Time(const Time &tm) :
+       timezone_(tm.timezone_),
+       milliseconds_(tm.milliseconds_)
 {
-       time_t ct;
-       struct tm *ct_tm;
+}
 
-       time(&ct);
-       ct_tm = localtime(&ct);
-       return Time(ct_tm->tm_hour, ct_tm->tm_min, 0);
+int Time::GetTimezoneOffset(const char *timezone_id)
+{
+       i18n_timezone_h handle;
+       int32_t offset;
+       int err = i18n_timezone_create(&handle, timezone_id);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_timezone_create failed[%d]: %s", err, get_error_message(err));
+               return INT_MAX;
+       }
+       err = i18n_timezone_get_raw_offset(handle, &offset);
+       if (err != I18N_ERROR_NONE) {
+               ERR("i18n_timezone_get_raw_offset failed[%d]: %s", err, get_error_message(err));
+               i18n_timezone_destroy(handle);
+               return INT_MAX;
+       }
+       i18n_timezone_destroy(handle);
+       return offset / (60 * 1000);
 }
index c0f0cb0..a28c874 100644 (file)
@@ -111,9 +111,9 @@ static char *Time2FormattedString(const Time &time)
 {
        std::stringstream formatted_time;
 
-       formatted_time << time.Format(FORMAT_12H);
+       formatted_time << time.Format(Time::FORMAT_TIME_12H);
        formatted_time << " <meridiem>";
-       formatted_time << time.Meridiem();
+       formatted_time << time.Format(Time::FORMAT_TIME_AMPM);
        formatted_time << "</meridiem>";
 
        return strdup(formatted_time.str().c_str());
index 6039c5c..378d517 100644 (file)
@@ -38,9 +38,9 @@ static char *Time2FormattedString(const Time &time)
 {
        std::stringstream formatted_time;
 
-       formatted_time << time.Format(FORMAT_12H);
+       formatted_time << time.Format(Time::FORMAT_TIME_12H);
        formatted_time << " <meridiem>";
-       formatted_time << time.Meridiem();
+       formatted_time << time.Format(Time::FORMAT_TIME_AMPM);
        formatted_time << "</meridiem>";
 
        return strdup(formatted_time.str().c_str());
index ee6fe7c..5598f01 100644 (file)
@@ -60,21 +60,41 @@ static std::string GetLabelForWeekFlag(WeekFlags &flag)
        return label;
 }
 
-inline static Elm_Datetime_Time ConvertTimeToElmDatetimeTime(const Time &atime)
+inline static Time::Month ConvertTmMont2TimeMonth(int mon)
 {
-       Elm_Datetime_Time elm_time = {0,};
-       // set valid year, according to elm_datetime doc default years range is between
-       // 1970-2037
-       elm_time.tm_year = 100; // + 1900
-       elm_time.tm_hour = atime.Hour;
-       elm_time.tm_min = atime.Min;
-       elm_time.tm_sec = atime.Sec;
-       return elm_time;
+       switch (mon) {
+               case 0:
+                       return Time::Month::January;
+               case 1:
+                       return Time::Month::Febuary;
+               case 2:
+                       return Time::Month::March;
+               case 3:
+                       return Time::Month::April;
+               case 4:
+                       return Time::Month::May;
+               case 5:
+                       return Time::Month::June;
+               case 6:
+                       return Time::Month::July;
+               case 7:
+                       return Time::Month::August;
+               case 8:
+                       return Time::Month::September;
+               case 9:
+                       return Time::Month::October;
+               case 10:
+                       return Time::Month::November;
+               case 11:
+                       return Time::Month::December;
+       }
+       FAT("Invalid struct tm month value");
 }
 
 inline static Time ConvertElmDatetimeTimeToTime(const Elm_Datetime_Time &time)
 {
-       return Time(time.tm_hour, time.tm_min, time.tm_sec);
+       return Time(time.tm_year + 1900, ConvertTmMont2TimeMonth(time.tm_mon), time.tm_mday,
+                       time.tm_hour, time.tm_min, 0, 0);
 }
 
 static const char *GetLabelForAlarmType(AlarmType type)
@@ -141,6 +161,8 @@ void EditAlarmView::CreateContent()
        elm_theme_extension_add(NULL,
             Utils::GetAppResourcePath(Utils::APP_DIR_RESOURCE, "edje/edit_alarm.edj"));
 
+       data_.time = Time::Now();
+
        CreateGenlistItems();
 }
 
@@ -220,7 +242,7 @@ void EditAlarmView::CreateGenlistItems()
                elm_object_style_set(dt, "time_layout"); // from tizen-theme
                evas_object_smart_callback_add(dt, "changed"
                                , EditAlarmView::DateTimeChangedCallback, view);
-               auto elm_time = ConvertTimeToElmDatetimeTime(view->data_.time);
+               auto elm_time = view->data_.time.GetTmStruct();
                elm_datetime_value_set(dt, &elm_time);
                evas_object_show(dt);
                return dt;
index 567090d..34ca405 100644 (file)
@@ -66,10 +66,45 @@ void WorldClockView::CreateCustomLocationsList()
        elm_layout_content_set(world_clock_, TIMEZONE_CUSTOM_LOCATIONS_LIST_PART, custom_locations_list_);
 }
 
+// local_timezone_offset and timezone_offset should be relative to GMT
+std::string GetTimezoneDiffDescription(int local_timezone_offset, int timezone_offset)
+{
+       char *pattern;
+       char relative[128] = { 0, };
+
+       int offset_integer = (abs(timezone_offset - local_timezone_offset)) / 60;
+       int offset_remainder = (abs(timezone_offset - local_timezone_offset)) % 60;
+
+       if (timezone_offset < local_timezone_offset) {
+               if (offset_remainder > 0) {
+                               pattern = _("IDS_CLOCK_BODY_PS1D_H_P2SD_M_BEHIND_ABB");
+                               snprintf(relative, sizeof(relative), pattern, offset_integer,
+                               offset_remainder);
+               } else {
+                       pattern = _("IDS_CLOCK_BODY_PD_H_BEHIND_ABB");
+                       snprintf(relative, sizeof(relative), pattern, offset_integer);
+               }
+       } else if (timezone_offset > local_timezone_offset) {
+               if (offset_remainder > 0) {
+                       pattern = _("IDS_CLOCK_BODY_PS1D_H_P2SD_M_AHEAD_ABB");
+                       snprintf(relative, sizeof(relative), pattern, offset_integer,
+                       offset_remainder);
+               } else {
+                       pattern = _("IDS_CLOCK_BODY_PD_H_AHEAD_ABB");
+                       snprintf(relative, sizeof(relative), pattern, offset_integer);
+               }
+       } else {
+               snprintf(relative, sizeof(relative), "Same as local time");
+       }
+       return std::string(&relative[0]);
+}
+
 void WorldClockView::AppendItemToCustomList(const model::Location *location)
 {
        LocationItemData *data = new LocationItemData;
-       Time t;
+       Time t = Time::Now().InTimezone(
+                       Time::GetTimezoneNameByOffset(location->gmt_offset_).c_str());;
+       int local_timezone_offset = Time::GetTimezoneOffset(Time::GetCurrentTimezone().c_str());
        std::stringstream ss;
 
        data->location = location;
@@ -77,10 +112,11 @@ void WorldClockView::AppendItemToCustomList(const model::Location *location)
        ss << location->name << ", " << location->country;
        data->city_country = strdup(ss.str().c_str());
 
-       data->ampm = strdup(t.GetMeridiemByOffset(location->gmt_offset_).c_str());
-       data->gmt_offset_relative = strdup(t.GetTimezoneRelativeToLocalString(location->gmt_offset_).c_str());
+       data->ampm = strdup(t.Format("a").c_str());
+       data->gmt_offset_relative = strdup(
+                       GetTimezoneDiffDescription(local_timezone_offset, location->gmt_offset_).c_str());
        data->gmt_offset = location->gmt_offset_;
-       data->date = strdup(t.GetTimezoneDate(location->gmt_offset_).c_str());
+       data->date = strdup(t.Format("E d MMM").c_str());
 
        data->it = elm_genlist_item_append(custom_locations_list_,
                        &world_clock_itc_,
@@ -125,16 +161,15 @@ Evas_Object *WorldClockView::ContentGet(void *data, Evas_Object *obj, const char
                elm_table_pack(lid->time, ampm, 2, 0, 1, 1);
                elm_table_pack(lid->time, dynamic_padding, 3, 0, 1, 1);
 
-               //TODO Time need to be set as current for specific timezone
-               Time t;
+               Time t = Time::Now().InTimezone(Time::GetTimezoneNameByOffset(lid->gmt_offset).c_str());
 
-               std::string timezone_time = t.GetFormattedTimeByTimezoneOffset("HH:MM", lid->gmt_offset);
+               std::string timezone_time = t.Format("HH:mm");
                char time_formatted[MAX_STYLE_LEN] = { 0, };
                snprintf(time_formatted, sizeof(time_formatted),
                                CUSTOM_LIST_TIME_STYLE("%s"), timezone_time.c_str());
                elm_object_text_set(time, time_formatted);
 
-               std::string meridiem = t.GetMeridiemByOffset(lid->gmt_offset);
+               std::string meridiem = t.Format("a");
                char ampm_formatted[MAX_STYLE_LEN] = { 0, };
                snprintf(ampm_formatted, sizeof(ampm_formatted),
                                CUSTOM_LIST_AMPM_STYLE("%s"), meridiem.c_str());
@@ -509,10 +544,10 @@ Evas_Object *WorldClockView::CreateTimezoneTime(Evas_Object *parent)
 
 void WorldClockView::UpdateTimezoneTime(int timezone_offset)
 {
-       Time t;
+       Time t = Time::Now().InTimezone(Time::GetTimezoneNameByOffset(
+                               timezone_offset).c_str());
 
-       //TODO This must be formated according to global device settings
-       std::string timezone_time = t.GetFormattedTimeByTimezoneOffset("HH:MM", timezone_offset);
+       std::string timezone_time = t.Format("HH:mm");
 
        char time_formatted[MAX_STYLE_LEN] = { 0, };
        snprintf(time_formatted, sizeof(time_formatted),
@@ -532,10 +567,9 @@ Evas_Object *WorldClockView::CreateTimezoneXMeridiem(Evas_Object *parent)
 
 void WorldClockView::UpdateTimezoneXMeridiem(int timezone_offset)
 {
-       Time t;
+       Time t = Time::Now().InTimezone(Time::GetTimezoneNameByOffset(timezone_offset).c_str());
 
-       //TODO This must be formated according to global device settings
-       std::string meridiem = t.GetMeridiemByOffset(timezone_offset);
+       std::string meridiem = t.Format(Time::FORMAT_TIME_AMPM);
 
        char ampm_formatted[MAX_STYLE_LEN] = { 0, };
        snprintf(ampm_formatted, sizeof(ampm_formatted),
@@ -555,12 +589,12 @@ Evas_Object *WorldClockView::CreateTimezoneRelativeToLocalObject(Evas_Object *pa
 
 void WorldClockView::UpdateTimezoneRelativeToLocal(int timezone_offset)
 {
-       Time t;
+       int local_timezone_offset = Time::GetTimezoneOffset(Time::GetCurrentTimezone().c_str());
 
        char relative_formatted[MAX_STYLE_LEN] = { 0, };
        snprintf(relative_formatted, sizeof(relative_formatted),
                TIMEZONE_DETAILS_FIRST_LINE_RELATIVE_TO_LOCAL_STYLE("%s"),
-               t.GetTimezoneRelativeToLocalString(timezone_offset).c_str());
+               GetTimezoneDiffDescription(local_timezone_offset, timezone_offset).c_str());
 
        elm_object_text_set(elm_table_child_get(timezone_details_, 4, 0), relative_formatted);
 }