tizen 2.3.1 release
[framework/web/mobile/wrt-plugins-tizen.git] / src / TimeUtil / TZDate.cpp
1 //
2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        TZDate.cpp
20  */
21
22 #include "TZDate.h"
23 #include "TimeUtilTools.h"
24 #include <unicode/unistr.h>
25 #include <unicode/timezone.h>
26 #include <unicode/calendar.h>
27 #include <unicode/ucal.h>
28 #include <unicode/vtzone.h>
29 #include <unicode/smpdtfmt.h>
30
31 #ifdef IMPL_BACKWARD_COMPATIBLE
32 #include <Commons/Exception.h>
33
34 using namespace WrtDeviceApis;
35 #endif // IMPL_BACKWARD_COMPATIBLE
36
37 namespace DeviceAPI {
38 namespace Time {
39
40 TZDate::TZDate()
41 {
42     UErrorCode ec = U_ZERO_ERROR;
43     TimeUtilTools util;
44     m_calendar = Calendar::createInstance(ec);
45
46     if (U_SUCCESS(ec)) {
47         LOGD("Calendar created successfully");
48     } else {
49         LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
50     }
51 }
52
53 TZDate::TZDate(time_t datetime, std::string timezone)
54 {
55     UErrorCode ec = U_ZERO_ERROR;
56     long local_offset = 0;
57     std::string local_timezone = TimeUtilTools::getLocalTimeZone();
58     UnicodeString* usTimezone = TimeUtilTools::toUnicodeString(local_timezone);
59     TimeZone* tz = TimeZone::createTimeZone(*usTimezone);
60     delete usTimezone;
61     local_offset = tz->getRawOffset();
62     if (timezone.empty() || !TimeUtilTools::isInTimezonesArray(timezone)) {
63         timezone = TimeUtilTools::getLocalTimeZone();
64     }
65
66     usTimezone = TimeUtilTools::toUnicodeString(timezone);
67     tz = TimeZone::createTimeZone(*usTimezone);
68     delete usTimezone;
69
70     if (!datetime) {
71         datetime = time(NULL);
72     }
73     datetime += local_offset / 1000;
74     timeval tp;
75     gettimeofday(&tp, NULL);
76     struct tm *date = gmtime(&datetime);
77     m_calendar = Calendar::createInstance(*tz, ec);
78
79     if (U_SUCCESS(ec)) {
80         m_calendar->set(TimeUtilTools::toint32_t(date->tm_year + 1900),
81                 TimeUtilTools::toint32_t(date->tm_mon),
82                 TimeUtilTools::toint32_t(date->tm_mday), TimeUtilTools::toint32_t(date->tm_hour),
83                 TimeUtilTools::toint32_t(date->tm_min), TimeUtilTools::toint32_t(date->tm_sec));
84         m_calendar->set(UCAL_MILLISECOND, TimeUtilTools::toint32_t(tp.tv_usec / 1000));
85     }
86     else {
87         m_calendar = NULL;
88         LOGE("Calendar doesn't created: %d, %s", ec, u_errorName(ec));
89     }
90
91 }
92
93 TZDate::TZDate(long year,
94         long month,
95         long day,
96         long hours,
97         long minutes,
98         long seconds,
99         long milliseconds,
100         std::string timezone)
101 {
102     UErrorCode ec = U_ZERO_ERROR;
103     if (timezone.empty() || !TimeUtilTools::isInTimezonesArray(timezone)) {
104         timezone = TimeUtilTools::getLocalTimeZone();
105     }
106     std::shared_ptr<UnicodeString> usTimezone(TimeUtilTools::toUnicodeString(timezone));
107     TimeZone* tz = TimeZone::createTimeZone(*usTimezone);
108     m_calendar = Calendar::createInstance(*tz, ec);
109
110     if (U_SUCCESS(ec)) {
111         m_calendar->set(TimeUtilTools::toint32_t(year), TimeUtilTools::toint32_t(month),
112                 TimeUtilTools::toint32_t(day), TimeUtilTools::toint32_t(hours),
113                 TimeUtilTools::toint32_t(minutes), TimeUtilTools::toint32_t(seconds));
114         m_calendar->set(UCAL_MILLISECOND, TimeUtilTools::toint32_t(milliseconds));
115     }
116     else {
117         m_calendar = NULL;
118         LOGE("Calendar doesn't created: %d, %s", ec, u_errorName(ec));
119     }
120 }
121
122 TZDate::TZDate(const TZDate& tzdate) {
123     m_calendar = tzdate.m_calendar->clone();
124 }
125
126 TZDate::TZDate(Calendar* cal) {
127     m_calendar = cal;
128 }
129
130 TZDate& TZDate::operator =( const TZDate& tzdate)
131 {
132     if (this != &tzdate) {
133         delete m_calendar;
134         m_calendar = tzdate.m_calendar->clone();
135     }
136     return *this;
137 }
138
139 TZDate::~TZDate()
140 {
141     if (m_calendar) {
142         delete m_calendar;
143         m_calendar = NULL;
144     }
145
146 }
147
148 long TZDate::getDate() const {
149     UErrorCode ec = U_ZERO_ERROR;
150     return TimeUtilTools::tolong(m_calendar->get(UCAL_DATE, ec));
151 }
152
153 void TZDate::setDate(long date) {
154     m_calendar->set(UCAL_DATE, TimeUtilTools::toint32_t(date));
155 }
156
157 long TZDate::getDay() const {
158     UErrorCode ec = U_ZERO_ERROR;
159     return TimeUtilTools::tolong(m_calendar->get(UCAL_DAY_OF_WEEK, ec)) - 1; // -1 because enums values begins from 1
160 }
161
162 long TZDate::getFullYear() const {
163     UErrorCode ec = U_ZERO_ERROR;
164     return TimeUtilTools::tolong(m_calendar->get(UCAL_YEAR, ec));
165 }
166
167 void TZDate::setFullYear(long year) {
168     if (year <= 0) {
169         year = 1;
170     }
171     m_calendar->set(UCAL_YEAR, TimeUtilTools::toint32_t(year));
172 }
173
174 long TZDate::getHours() const {
175     UErrorCode ec = U_ZERO_ERROR;
176     return TimeUtilTools::tolong(m_calendar->get(UCAL_HOUR_OF_DAY, ec));
177 }
178
179 void TZDate::setHours(long hours) {
180     m_calendar->set(UCAL_HOUR_OF_DAY, TimeUtilTools::toint32_t(hours));
181 }
182
183 long TZDate::getMilliseconds() const {
184     UErrorCode ec = U_ZERO_ERROR;
185     return TimeUtilTools::tolong(m_calendar->get(UCAL_MILLISECOND, ec));
186 }
187
188 void TZDate::setMilliseconds(long ms) {
189     m_calendar->set(UCAL_MILLISECOND, TimeUtilTools::toint32_t(ms));
190 }
191
192 long TZDate::getMinutes() const {
193     UErrorCode ec = U_ZERO_ERROR;
194     return TimeUtilTools::tolong(m_calendar->get(UCAL_MINUTE, ec));
195 }
196
197 void TZDate::setMinutes(long minutes) {
198     m_calendar->set(UCAL_MINUTE, TimeUtilTools::toint32_t(minutes));
199 }
200
201 long TZDate::getMonth() const {
202     UErrorCode ec = U_ZERO_ERROR;
203     return TimeUtilTools::tolong(m_calendar->get(UCAL_MONTH, ec));
204 }
205
206 void TZDate::setMonth(long month) {
207     m_calendar->set(UCAL_MONTH, TimeUtilTools::toint32_t(month));
208 }
209
210 long TZDate::getSeconds() const {
211     UErrorCode ec = U_ZERO_ERROR;
212     return m_calendar->get(UCAL_SECOND, ec);
213 }
214
215 void TZDate::setSeconds(long seconds) {
216     m_calendar->set(UCAL_SECOND, TimeUtilTools::toint32_t(seconds));
217 }
218
219 long TZDate::getUTCDate() const {
220     UErrorCode ec = U_ZERO_ERROR;
221     Calendar* cal = getUTCCalendar();
222     int32_t value = cal->get(UCAL_DATE, ec);
223     if (!U_SUCCESS(ec)) {
224         LOGE("Can't get date from cal: %d, %s", ec, u_errorName(ec));
225         throw Common::UnknownException("Can't get date from cal");
226     }
227
228     delete cal;
229     cal = NULL;
230
231     return TimeUtilTools::tolong(value);
232 }
233
234 void TZDate::setUTCDate(long date) {
235     long val = getUTCDate();
236     setDate(getDate() + date - val);
237 }
238
239 long TZDate::getUTCDay() const {
240     UErrorCode ec = U_ZERO_ERROR;
241     Calendar* cal = getUTCCalendar();
242     int32_t value = cal->get(UCAL_DAY_OF_WEEK, ec);
243     if (!U_SUCCESS(ec)) {
244         LOGE("Can't get day from cal: %d, %s", ec, u_errorName(ec));
245         throw Common::UnknownException("Can't get day from cal");
246     }
247
248     delete cal;
249     cal = NULL;
250
251     return TimeUtilTools::tolong(value-1); // -1 because enums values begins from 1
252 }
253
254 long TZDate::getUTCFullYear() const {
255     UErrorCode ec = U_ZERO_ERROR;
256     Calendar* cal = getUTCCalendar();
257     int32_t value = cal->get(UCAL_YEAR, ec);
258     if (!U_SUCCESS(ec)) {
259         LOGE("Can't get year from cal: %d, %s", ec, u_errorName(ec));
260         throw Common::UnknownException("Can't get year from cal");
261     }
262
263     delete cal;
264     cal = NULL;
265
266     return TimeUtilTools::tolong(value);
267 }
268
269 void TZDate::setUTCFullYear(long year) {
270     long val = getUTCFullYear();
271     setFullYear(getFullYear() + year - val);
272 }
273
274 long TZDate::getUTCHours() const {
275     UErrorCode ec = U_ZERO_ERROR;
276     Calendar* cal = getUTCCalendar();
277     int32_t value = cal->get(UCAL_HOUR_OF_DAY, ec);
278     if (!U_SUCCESS(ec)) {
279         LOGE("Can't get hours from cal: %d, %s", ec, u_errorName(ec));
280         throw Common::UnknownException("Can't get hours from cal");
281     }
282
283     delete cal;
284     cal = NULL;
285
286     return TimeUtilTools::tolong(value);
287 }
288
289 void TZDate::setUTCHours(long hours) {
290     long val = getUTCHours();
291     setHours(getHours() + hours - val);
292 }
293
294 long TZDate::getUTCMilliseconds() const {
295     return getMilliseconds();
296 }
297
298 void TZDate::setUTCMilliseconds(long ms) {
299     setMilliseconds(ms);
300 }
301
302 long TZDate::getUTCMinutes() const {
303     return getMinutes();
304 }
305
306 void TZDate::setUTCMinutes(long minutes) {
307     setMinutes(minutes);
308 }
309
310 long TZDate::getUTCMonth() const {
311     UErrorCode ec = U_ZERO_ERROR;
312     Calendar* cal = getUTCCalendar();
313     int32_t value = cal->get(UCAL_MONTH, ec);
314     if (!U_SUCCESS(ec)) {
315         LOGE("Can't get month from cal: %d, %s", ec, u_errorName(ec));
316         throw Common::UnknownException("Can't get month from cal");
317     }
318
319     delete cal;
320     cal = NULL;
321
322     return TimeUtilTools::tolong(value);
323 }
324
325 void TZDate::setUTCMonth(long month) {
326     long val = getUTCMonth();
327     setMonth(getMonth() + month - val);
328 }
329
330 long TZDate::getUTCSeconds() const {
331     return getSeconds();
332 }
333
334 void TZDate::setUTCSeconds(long seconds) {
335     setSeconds(seconds);
336 }
337
338 std::string TZDate::getTimezone() const {
339     UnicodeString id;
340
341     m_calendar->getTimeZone().getID(id);
342     return TimeUtilTools::toUTF8String(id);
343 }
344
345 TZDatePtr TZDate::toTimezone(const std::string& tzid) const {
346     TZDatePtr newObj;
347     if (TimeUtilTools::isInTimezonesArray(tzid)) {
348         newObj = TZDatePtr(new (std::nothrow) TZDate(getCalendar(tzid)));
349         if (!newObj) {
350             LOGE("Object not created");
351             throw Common::UnknownException("Object not created");
352         }
353     } else {
354         LOGE("Invalid timezone");
355         throw Common::InvalidValuesException("Invalid timezone");
356     }
357     return newObj;
358 }
359
360 TZDatePtr TZDate::toLocalTimezone() const {
361     std::string localTimezone = TimeUtilTools::getLocalTimeZone();
362     return toTimezone(localTimezone);
363 }
364
365 TZDatePtr TZDate::toUTC() const {
366     TZDatePtr newObj = TZDatePtr(new (std::nothrow) TZDate(getUTCCalendar()));
367     if (!newObj) {
368         LOGE("Object not created");
369         throw Common::UnknownException("Object not created");
370     }
371     return newObj;
372 }
373
374 TimeDurationPtr TZDate::difference(TZDatePtr other) const {
375     TimeDurationPtr dur = TimeDurationPtr(new (std::nothrow) TimeDuration());
376     UDate thisTime, otherTime, diffTime;
377     long long len = 0;
378     UErrorCode ec = U_ZERO_ERROR;
379     TZDatePtr newObj = other;
380
381     diffTime = m_calendar->getTime(ec) - newObj->m_calendar->getTime(ec);
382
383     if (fabs(diffTime) > LLONG_MAX) {
384         LOGE("limit value reached");
385         throw Common::UnknownException("limit value reached");
386     }
387     len = static_cast<long long>(diffTime);
388
389     if (len % TIME_DAYS_UNIT == 0) {
390         len = len / TIME_DAYS_UNIT;
391         dur->setUnit(DAYS);
392     }
393     dur->setLength(len);
394
395     return dur;
396 }
397
398 bool TZDate::equalsTo(TZDatePtr other) const {
399     TimeDurationPtr dur = difference(other);
400     return !dur->getLength();
401 }
402
403 bool TZDate::earlierThan(TZDatePtr other) const {
404     TimeDurationPtr dur = difference(other);
405     return dur->getLength() < 0;
406 }
407
408 bool TZDate::laterThan(TZDatePtr other) const {
409     TimeDurationPtr dur = difference(other);
410     return dur->getLength() > 0;
411 }
412
413 TZDatePtr TZDate::addDuration(TimeDurationPtr duration) const {
414     TZDatePtr newObj = TZDatePtr(new (std::nothrow) TZDate());
415     TimeDuration::findTheBiggestPossibleUnit(duration);
416     long long len = duration->getLength();
417     std::string unit = duration->getUnit();
418
419     UErrorCode ec = U_ZERO_ERROR;
420     newObj->m_calendar = m_calendar->clone();
421
422     if (MSECS == unit) {
423         newObj->m_calendar->add(UCAL_MILLISECOND,
424                 TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
425     } else if (SECS == unit) {
426         newObj->m_calendar->add(UCAL_SECOND,
427                 TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
428     } else if (MINS == unit) {
429         newObj->m_calendar->add(UCAL_MINUTE,
430                 TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
431     } else if (HOURS == unit) {
432         newObj->m_calendar->add(UCAL_HOUR_OF_DAY,
433                 TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
434     } else if (DAYS == unit) {
435         newObj->m_calendar->add(UCAL_DATE,
436                 TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
437     }
438     return newObj;
439 }
440
441 std::string TZDate::toLocaleDateString() const {
442     return toString(true, TimeUtilTools::DATE_FORMAT);
443 }
444
445 std::string TZDate::toLocaleTimeString() const {
446     return toString(true, TimeUtilTools::TIME_FORMAT);
447 }
448
449 std::string TZDate::toLocaleString() const {
450     return toString(true);
451 }
452
453 std::string TZDate::toDateString() const {
454     return toString(false, TimeUtilTools::DATE_FORMAT);
455 }
456
457 std::string TZDate::toTimeString() const {
458     return toString(false, TimeUtilTools::TIME_FORMAT);
459 }
460
461 std::string TZDate::toString(bool bLocale,
462         TimeUtilTools::DateTimeFormatType type) const {
463     UErrorCode ec = U_ZERO_ERROR;
464     UnicodeString str;
465
466     Locale* defaultLocale = TimeUtilTools::getDefaultLocale();
467     DateFormat* fmt = new SimpleDateFormat(TimeUtilTools::getDateTimeFormat(type, bLocale),
468             ((bLocale && defaultLocale != NULL) ? *defaultLocale : Locale::getEnglish()), ec);
469
470     if (!fmt) {
471         LOGE("new SimpleDateFormat returned null");
472         throw Common::UnknownException("new SimpleDateFormat returned null");
473     }
474
475     if (U_SUCCESS(ec)) {
476         fmt->setCalendar(*m_calendar);
477         fmt->format(m_calendar->getTime(ec), str);
478         delete fmt;
479         fmt = NULL;
480         if (U_SUCCESS(ec)) {
481             std::string result = TimeUtilTools::toUTF8String(str);
482             str.remove();
483             return result;
484         } else {
485             LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
486         }
487
488     }
489     LOGE("can't make SimpleDateFormat or can't get time: %d, %s", ec, u_errorName(ec));
490     throw Common::UnknownException("can't make SimpleDateFormat or can't get time");
491 }
492
493 std::string TZDate::getTimezoneAbbreviation() const {
494     LOGD("entered");
495     if (m_calendar == NULL) {
496          throw Common::UnknownException("can't make SimpleDateFormat or can't get time");
497     }
498
499     UnicodeString str;
500
501     m_calendar->getTimeZone().getDisplayName(isDST(), TimeZone::SHORT, Locale::getEnglish(), str);
502     if ((str != "GMT") && (str.length() > 3) && !str.compare(0, 3, "GMT")) {
503         m_calendar->getTimeZone().getDisplayName(isDST(), TimeZone::LONG_GMT, Locale::getEnglish(), str);
504     }
505     std::string result = TimeUtilTools::toUTF8String(str);
506     str.remove();
507     LOGD ("%s", result.c_str());
508     return result;
509 }
510
511 long TZDate::secondsFromUTC() const {
512     UErrorCode ec = U_ZERO_ERROR;
513     return (m_calendar->get(UCAL_ZONE_OFFSET, ec) + m_calendar->get(UCAL_DST_OFFSET, ec)) * (-1) / 1000;
514 }
515
516 bool TZDate::isDST() const {
517     UErrorCode ec = U_ZERO_ERROR;
518     UBool result = m_calendar->inDaylightTime(ec);
519     return static_cast<bool>(result);
520 }
521
522 TZDatePtr TZDate::getPreviousDSTTransition() const {
523     return getDSTTransition(PREVDST);
524 }
525
526 TZDatePtr TZDate::getNextDSTTransition() const {
527     return getDSTTransition(NEXTDST);
528 }
529
530 TZDatePtr TZDate::getDSTTransition(DSTTransition tr_type) const
531 {
532     UErrorCode ec = U_ZERO_ERROR;
533     UBool result = false;
534     UDate dstTransitionDate = m_calendar->getTime(ec);
535     if (U_SUCCESS(ec)) {
536         UnicodeString *id = TimeUtilTools::toUnicodeString(getTimezone());
537         VTimeZone *vtz = VTimeZone::createVTimeZoneByID(*id);
538         delete id;
539         id = NULL;
540
541         TimeZoneTransition tzTrans;
542         if (vtz->useDaylightTime()) {
543             if (NEXTDST == tr_type) {
544                 result = vtz->getNextTransition(dstTransitionDate, FALSE, tzTrans);
545             }
546             else if (PREVDST == tr_type) {
547                 result = vtz->getPreviousTransition(dstTransitionDate, FALSE, tzTrans);
548             }
549             else {
550                 LOGD("invalid comparison value");
551                 result = false;
552             }
553             if (result) {
554                 dstTransitionDate = tzTrans.getTime();
555             }
556         }
557         delete vtz;
558         vtz = NULL;
559
560         TZDatePtr newObj = TZDatePtr(new (std::nothrow) TZDate(*this));
561         if (!result) {
562             return newObj;
563         }
564         newObj->m_calendar->setTime(dstTransitionDate, ec);
565         if (U_SUCCESS(ec)) {
566             return newObj;
567         } else {
568             LOGE("Failed to set time: %d, %s", ec, u_errorName(ec));
569         }
570     }
571     LOGE("can't getDSTTransition value from ICU: %d, %s", ec, u_errorName(ec));
572     throw Common::UnknownException("can't getDSTTransition value from ICU");
573 }
574
575 icu::Calendar* TZDate::getCalendar(const std::string& timezone) const {
576     UErrorCode ec = U_ZERO_ERROR;
577     std::shared_ptr<UnicodeString> usTimezone (TimeUtilTools::toUnicodeString(timezone));
578     icu::Calendar *cal = Calendar::createInstance(*(TimeZone::createTimeZone(*usTimezone)), ec);
579
580     if (!U_SUCCESS(ec)) {
581         LOGE("Can't create cal: %d, %s", ec, u_errorName(ec));
582         throw Common::UnknownException("Can't create cal");
583     }
584     UDate date = m_calendar->getTime(ec);
585     if (!U_SUCCESS(ec)) {
586         LOGE("Can't get time of m_calendar: %d, %s", ec, u_errorName(ec));
587         throw Common::UnknownException("Can't get time of m_calendar");
588     }
589     cal->setTime(date, ec);
590     if (!U_SUCCESS(ec)) {
591         LOGE("Can't get time of cal: %d, %s", ec, u_errorName(ec));
592         throw Common::UnknownException("Can't get time of cal");
593     }
594     return cal;
595 }
596
597 icu::Calendar* TZDate::getUTCCalendar() const {
598     UErrorCode ec = U_ZERO_ERROR;
599     icu::Calendar *cal = Calendar::createInstance(*(TimeZone::getGMT()), ec);
600
601     if (!U_SUCCESS(ec)) {
602         LOGE("Can't create cal: %d, %s", ec, u_errorName(ec));
603         throw Common::UnknownException("Can't create cal");
604     }
605     UDate date = m_calendar->getTime(ec);
606     if (!U_SUCCESS(ec)) {
607         LOGE("Can't get time of m_calendar: %d, %s", ec, u_errorName(ec));
608         throw Common::UnknownException("Can't get time of m_calendar");
609     }
610     cal->setTime(date, ec);
611     if (!U_SUCCESS(ec)) {
612         LOGE("Can't get time of cal: %d, %s", ec, u_errorName(ec));
613         throw Common::UnknownException("Can't get time of cal");
614     }
615     return cal;
616 }
617
618 void TZDate::setTimezone(const std::string& timezone, bool timezone_is_certain) {
619     if (!timezone_is_certain) {
620         timezone_is_certain = TimeUtilTools::isInTimezonesArray(timezone);
621     }
622
623     if (timezone_is_certain) {
624         std::shared_ptr<UnicodeString> usTimezone(TimeUtilTools::toUnicodeString(timezone));
625         TimeZone* tz = TimeZone::createTimeZone(*usTimezone);
626         m_calendar->adoptTimeZone(tz);
627     }
628     else {
629         LOGD("Invalid timezone");
630     }
631 }
632
633 #ifdef IMPL_BACKWARD_COMPATIBLE
634 TZDate::TZDate(const std::string &timezone)
635 {
636     LOGD("entered");
637
638     UErrorCode ec = U_ZERO_ERROR;
639     TimeUtilTools util;
640     TimeZone *tz = util.makeTimeZone(timezone);
641     if (isAvailableTimezone(tz)) {
642         m_calendar= Calendar::createInstance(tz ,ec);
643     } else {
644         if (tz) {
645             delete tz;
646         }
647         m_calendar = Calendar::createInstance(ec);
648     }
649
650     if (U_SUCCESS(ec)) {
651         util.printDate(m_calendar);
652     } else {
653         LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
654         m_calendar = NULL;
655     }
656
657 }
658
659 TZDate::TZDate(const TZDateProperties &properties)
660 {
661     LOGD("entered");
662
663     TimeUtilTools util;
664     m_calendar= _makeCalendar(properties);
665 }
666
667 TZDate::TZDate(const std::string &dateString, const double milliseconds, const std::string &timezone)
668 {
669     m_calendar = NULL;
670
671     UErrorCode ec = U_ZERO_ERROR;
672     Calendar *dateCalender = Calendar::createInstance(ec);
673     DateFormat *df = NULL;
674     try {
675         if (dateCalender == NULL || U_FAILURE(ec)) {
676             ThrowMsg(Commons::UnknownException, "Can't make calendar");
677         }
678         df = new SimpleDateFormat("EEE MMM d uuuuuu HH:mm:ss", Locale::getEnglish(), ec);
679
680         if (df == NULL || U_FAILURE(ec)) {
681             ThrowMsg(Commons::UnknownException, "Can't make DateFormat");
682         }
683         ParsePosition pos;
684         pos.setIndex(0);
685         TimeUtilTools util;
686         UnicodeString text(dateString.c_str());
687         UDate date = df->parse(text, ec);
688
689         if (U_FAILURE(ec)) {
690             ThrowMsg(Commons::UnknownException, "parse fail");
691         }
692
693         dateCalender->setTime(date, ec);
694
695         if (U_FAILURE(ec)) {
696             ThrowMsg(Commons::UnknownException, "setTime fail");
697         }
698
699         util.printDate(dateCalender);
700         TZDateProperties properties;
701         properties.year = _get(TZDATE_YEAR, dateCalender);
702         properties.month = _get(TZDATE_MONTH, dateCalender);
703         properties.day = _get(TZDATE_DATE, dateCalender);
704         properties.hours = _get(TZDATE_HOUR_OF_DAY, dateCalender);
705         properties.minutes = _get(TZDATE_MINUTE, dateCalender);
706         properties.seconds = _get(TZDATE_SECOND, dateCalender);
707         properties.milliseconds = milliseconds;
708         properties.timezone = timezone;
709         m_calendar = _makeCalendar(properties);
710     } catch (const WrtDeviceApis::Commons::Exception& err) {
711         LOGE("%s : %s", err.GetClassName().c_str(), err.GetMessage().c_str());
712         if (m_calendar) {
713             delete m_calendar;
714         }
715         m_calendar = NULL;
716     }
717
718     if (dateCalender) {
719         delete dateCalender;
720     }
721     if (df) {
722         delete df;
723     }
724 }
725
726
727 bool TZDate::isAvailableTimezone(const std::string &timezone)
728 {
729     TimeUtilTools util;
730     TimeZone *tz = util.makeTimeZone(timezone);
731
732     bool result = isAvailableTimezone(tz);
733     
734     if (tz) {
735         delete tz;
736     }
737     return result;
738 }
739
740 bool TZDate::isAvailableTimezone(TimeZone *tz) {
741     TimeUtilTools util;
742     bool result = true;
743     UnicodeString id;
744     tz->getID(id);
745
746     if (util.toString(id) == "Etc/Unknown") {
747         result = false;
748     }
749
750     return result;
751 }
752
753 std::string TZDate::_getTimezoneName(Calendar *cal)
754 {
755     if (cal == NULL) {
756         ThrowMsg(Commons::UnknownException, "Invalid Date");
757     }
758
759     UnicodeString id;
760     TimeUtilTools util;
761
762     cal->getTimeZone().getID(id);
763     std::string s_result = util.toString(id);
764     LOGD("%s", s_result.c_str());
765     return s_result;
766 }
767
768 double TZDate::getTime() {
769     LOGD("entered");
770     if (m_calendar== NULL) {
771         LOGE("calendar is NULL");
772         ThrowMsg(Commons::UnknownException, "Invalid Date");
773     }
774
775     UErrorCode ec = U_ZERO_ERROR;
776
777     UDate date = m_calendar->getTime(ec);
778     if (U_SUCCESS(ec)) {
779         return static_cast<double>(date);
780     } else {
781         LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
782     }
783
784     ThrowMsg(Commons::PlatformException, "can't get time");
785 }
786
787 bool TZDate::setTime(const double time) {
788     LOGD("entered");
789     if (m_calendar == NULL)
790         ThrowMsg(Commons::UnknownException, "Invalid Date");
791
792     UErrorCode ec = U_ZERO_ERROR;
793
794     m_calendar->setTime(static_cast<UDate>(time), ec);
795     if (U_SUCCESS(ec)) {
796         return true;
797     } else {
798         LOGE("Failed to set time: %d, %s", ec, u_errorName(ec));
799     }
800
801     return false;
802 }
803
804 Calendar *TZDate::_makeCalendar(const TZDateProperties &properties)
805 {
806     LOGD("entered");
807     UErrorCode ec = U_ZERO_ERROR;
808     TimeUtilTools util;
809
810     Calendar *cal = NULL;
811     if ((properties.timezone == "") || !isAvailableTimezone(properties.timezone)) {
812         cal = Calendar::createInstance(ec);
813     } else {
814         cal = Calendar::createInstance(util.makeTimeZone(properties.timezone) ,ec);
815     }
816
817     if ((cal != NULL) && U_SUCCESS(ec)) {
818         try {
819             cal->set(UCAL_DATE, 10); //set specific date because first date(1) or last date(31) can make changing of month because of timezone
820     
821             _set(TZDATE_YEAR, properties.year, cal);
822             _set(TZDATE_MONTH, properties.month, cal);
823             _set(TZDATE_DATE, properties.day, cal);
824             _set(TZDATE_HOUR_OF_DAY, properties.hours, cal);
825             _set(TZDATE_MINUTE, properties.minutes, cal);
826             _set(TZDATE_SECOND, properties.seconds, cal);
827             _set(TZDATE_MILLISECOND, properties.milliseconds, cal);
828         } catch (const WrtDeviceApis::Commons::Exception& err) {
829             LOGE("%s : %s ", err.GetClassName().c_str(), err.GetMessage().c_str());
830             if (cal) {
831                 delete cal;
832             }
833             cal = NULL;
834         }
835         return cal;
836     } else {
837         LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
838     }
839
840     if (cal) {
841         delete cal;
842     }
843     return NULL;
844 }
845
846
847 long TZDate::_get(const TZDateFields field, Calendar *cal)
848 {
849     LOGD("<<<");
850
851     if (cal == NULL) {
852         ThrowMsg(Commons::UnknownException, "Invalid Date");
853     }
854
855     if (_convertDateField(field) == UCAL_FIELD_COUNT) {
856         LOGD(">>> UCAL_FIELD_COUNT");
857         return -1;
858     }
859
860     UErrorCode ec = U_ZERO_ERROR;
861     TimeUtilTools util;
862     int32_t value = cal->get(_convertDateField(field), ec);
863     if (U_SUCCESS(ec)) {
864         long result = util.tolong(value);
865
866         LOGD(">>> result: %ld", result);
867         return result;
868     }
869     LOGE("Failed to get calendar: %d, %s", ec, u_errorName(ec));
870     ThrowMsg(Commons::PlatformException, "Can't get Calendar value");
871 }
872
873 long TZDate::get(const TZDateFields field)
874 {
875     LOGD("<<<");
876
877     long result = _get(field, m_calendar);
878     if (field == TZDATE_DAY_OF_WEEK)
879         result--;
880     return result;
881 }
882
883
884 void TZDate::_set(const TZDateFields field, const long value, Calendar *cal)
885 {
886     if (_convertDateField(field) == UCAL_FIELD_COUNT) {
887         return;
888     }
889
890     if (cal == NULL) {
891         ThrowMsg(Commons::UnknownException, "Invalid Date");
892     }
893
894     TimeUtilTools util;
895     Calendar *originCal = cal->clone();
896     cal->set(_convertDateField(field), util.toint32_t(value));
897     
898     LOGD("Field : %d, value : %ld, result: %d", field, value, _get(field, cal));
899     try {
900         if (field == TZDATE_YEAR) {
901             if (value != _get(field, cal))
902                 ThrowMsg(Commons::PlatformException, "Out of range");
903         } else if (field == TZDATE_MONTH) {
904             long yearDiff = value / 12;
905             long month = value % 12;
906             if (value < 0) {
907                 yearDiff--;
908                 month += 12;
909             }
910             
911             long originYear = _get(TZDATE_YEAR, originCal);
912             if (((originYear + yearDiff) != _get(TZDATE_YEAR, cal))
913                 || (month != _get(TZDATE_MONTH, cal))) {
914                 LOGD("originYear: %ld, yearDiff: %ld, TZDATE_YEAR: %ld", originYear, yearDiff, _get(TZDATE_YEAR, cal));
915                 LOGD(" month: %ld, TZDATE_MONTH: %ld", month, _get(TZDATE_MONTH, cal));
916                 ThrowMsg(Commons::PlatformException, "Out of range");
917             }
918         } else {
919             UErrorCode ec = U_ZERO_ERROR;
920             double diff = value - _get(field, originCal);
921             if (field == TZDATE_DATE)
922                 diff *= U_MILLIS_PER_DAY;
923             else if (field == TZDATE_HOUR_OF_DAY)
924                 diff *= U_MILLIS_PER_HOUR;
925             else if (field == TZDATE_MINUTE)
926                 diff *= U_MILLIS_PER_MINUTE;
927             else if (field == TZDATE_SECOND)
928                 diff *= U_MILLIS_PER_SECOND;
929         
930             UDate originUDate = originCal->getTime(ec);
931             if (!U_SUCCESS(ec)) {
932                 LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
933                 ThrowMsg(Commons::PlatformException, "ICU Error");
934             }
935
936             LOGD("originUDate : %f, diff : %ld", (double)originUDate, diff);
937
938             if ((U_DATE_MAX - originUDate) < diff)
939                 ThrowMsg(Commons::PlatformException, "Out of range");
940         }
941     } catch (Commons::PlatformException& err) {
942         LOGE("%s", err.GetMessage().c_str());
943         if (originCal)
944             delete originCal;
945         throw(err);
946     }
947     if (originCal) {
948         delete originCal;
949     }
950 }
951
952 void TZDate::set(const TZDateFields field, const long value)
953 {
954     try {
955         _set(field, value, m_calendar);
956     } catch (Commons::PlatformException& err) {
957         LOGE("%s", err.GetMessage().c_str());
958         if (m_calendar) {
959             delete m_calendar;
960         }
961         m_calendar = NULL;
962     }
963 }
964
965 TZDateProperties TZDate::_makeProperties(Calendar *cal)
966 {
967     TZDateProperties result;
968     TimeUtilTools util;
969
970     result.year = _get(TZDATE_YEAR, cal);
971     result.month = _get(TZDATE_MONTH,cal);
972     result.day = _get(TZDATE_DATE, cal);
973     result.hours = _get(TZDATE_HOUR_OF_DAY, cal);
974     result.minutes = _get(TZDATE_MINUTE, cal);
975     result.seconds = _get(TZDATE_SECOND, cal);
976     result.milliseconds = _get(TZDATE_MILLISECOND, cal);
977     result.timezone=  _getTimezoneName(cal);
978
979     return result;
980 }
981
982 TZDateProperties TZDate::makeProperties()
983 {
984     return _makeProperties(m_calendar);
985 }
986
987
988
989 const UCalendarDateFields TZDate::_convertDateField(const TZDateFields field)
990 {
991     switch (field) {
992     case TZDATE_ERA:
993         return UCAL_ERA;
994         break;
995     case TZDATE_YEAR:
996         return UCAL_EXTENDED_YEAR;
997         break;
998     case TZDATE_MONTH:
999         return UCAL_MONTH;
1000         break;
1001     case TZDATE_WEEK_OF_YEAR:
1002         return UCAL_WEEK_OF_YEAR;
1003         break;
1004     case TZDATE_WEEK_OF_MONTH:
1005         return UCAL_WEEK_OF_MONTH;
1006         break;
1007     case TZDATE_DATE:
1008         return UCAL_DATE;
1009         break;
1010     case TZDATE_DAY_OF_YEAR:
1011         return UCAL_DAY_OF_YEAR;
1012         break;
1013     case TZDATE_DAY_OF_WEEK:
1014         return UCAL_DAY_OF_WEEK;
1015         break;
1016     case TZDATE_DAY_OF_WEEK_IN_MONTH:
1017         return UCAL_DAY_OF_WEEK_IN_MONTH;
1018         break;
1019     case TZDATE_AM_PM:
1020         return UCAL_AM_PM;
1021         break;
1022     case TZDATE_HOUR:
1023         return UCAL_HOUR;
1024         break;
1025     case TZDATE_HOUR_OF_DAY:
1026         return UCAL_HOUR_OF_DAY;
1027         break;
1028     case TZDATE_MINUTE:
1029         return UCAL_MINUTE;
1030         break;
1031     case TZDATE_SECOND:
1032         return UCAL_SECOND;
1033         break;
1034     case TZDATE_MILLISECOND:
1035         return UCAL_MILLISECOND;
1036         break;
1037     case TZDATE_ZONE_OFFSET:
1038         return UCAL_ZONE_OFFSET;
1039         break;
1040     case TZDATE_DST_OFFSET:
1041         return UCAL_DST_OFFSET;
1042         break;
1043     default:
1044         return UCAL_FIELD_COUNT;
1045     }
1046 }
1047
1048 #endif // IMPL_BACKWARD_COMPATIBLE
1049
1050
1051 } // Time
1052 } // DeviceAPI