tizen 2.3 release
[framework/web/wearable/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     if (U_SUCCESS(ec)) {
470         fmt->setCalendar(*m_calendar);
471         fmt->format(m_calendar->getTime(ec), str);
472         delete fmt;
473         fmt = NULL;
474         if (U_SUCCESS(ec)) {
475             std::string result = TimeUtilTools::toUTF8String(str);
476             str.remove();
477             return result;
478         } else {
479             LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
480         }
481
482     }
483     LOGE("can't make SimpleDateFormat or can't get time: %d, %s", ec, u_errorName(ec));
484     throw Common::UnknownException("can't make SimpleDateFormat or can't get time");
485 }
486
487 std::string TZDate::getTimezoneAbbreviation() const {
488     LOGD("entered");
489     if (m_calendar == NULL) {
490          throw Common::UnknownException("can't make SimpleDateFormat or can't get time");
491     }
492
493     UnicodeString str;
494
495     m_calendar->getTimeZone().getDisplayName(isDST(), TimeZone::SHORT, Locale::getEnglish(), str);
496     if ((str != "GMT") && (str.length() > 3) && !str.compare(0, 3, "GMT")) {
497         m_calendar->getTimeZone().getDisplayName(isDST(), TimeZone::LONG_GMT, Locale::getEnglish(), str);
498     }
499     std::string result = TimeUtilTools::toUTF8String(str);
500     str.remove();
501     LOGD ("%s", result.c_str());
502     return result;
503 }
504
505 long TZDate::secondsFromUTC() const {
506     UErrorCode ec = U_ZERO_ERROR;
507     return (m_calendar->get(UCAL_ZONE_OFFSET, ec) + m_calendar->get(UCAL_DST_OFFSET, ec)) * (-1) / 1000;
508 }
509
510 bool TZDate::isDST() const {
511     UErrorCode ec = U_ZERO_ERROR;
512     UBool result = m_calendar->inDaylightTime(ec);
513     return static_cast<bool>(result);
514 }
515
516 TZDatePtr TZDate::getPreviousDSTTransition() const {
517     return getDSTTransition(PREVDST);
518 }
519
520 TZDatePtr TZDate::getNextDSTTransition() const {
521     return getDSTTransition(NEXTDST);
522 }
523
524 TZDatePtr TZDate::getDSTTransition(DSTTransition tr_type) const
525 {
526     UErrorCode ec = U_ZERO_ERROR;
527     UBool result = false;
528     UDate dstTransitionDate = m_calendar->getTime(ec);
529     if (U_SUCCESS(ec)) {
530         UnicodeString *id = TimeUtilTools::toUnicodeString(getTimezone());
531         VTimeZone *vtz = VTimeZone::createVTimeZoneByID(*id);
532         delete id;
533         id = NULL;
534
535         TimeZoneTransition tzTrans;
536         if (vtz->useDaylightTime()) {
537             if (NEXTDST == tr_type) {
538                 result = vtz->getNextTransition(dstTransitionDate, FALSE, tzTrans);
539             }
540             else if (PREVDST == tr_type) {
541                 result = vtz->getPreviousTransition(dstTransitionDate, FALSE, tzTrans);
542             }
543             else {
544                 LOGD("invalid comparison value");
545                 result = false;
546             }
547             if (result) {
548                 dstTransitionDate = tzTrans.getTime();
549             }
550         }
551         delete vtz;
552         vtz = NULL;
553
554         TZDatePtr newObj = TZDatePtr(new (std::nothrow) TZDate(*this));
555         if (!result) {
556             return newObj;
557         }
558         newObj->m_calendar->setTime(dstTransitionDate, ec);
559         if (U_SUCCESS(ec)) {
560             return newObj;
561         } else {
562             LOGE("Failed to set time: %d, %s", ec, u_errorName(ec));
563         }
564     }
565     LOGE("can't getDSTTransition value from ICU: %d, %s", ec, u_errorName(ec));
566     throw Common::UnknownException("can't getDSTTransition value from ICU");
567 }
568
569 icu::Calendar* TZDate::getCalendar(const std::string& timezone) const {
570     UErrorCode ec = U_ZERO_ERROR;
571     std::shared_ptr<UnicodeString> usTimezone (TimeUtilTools::toUnicodeString(timezone));
572     icu::Calendar *cal = Calendar::createInstance(*(TimeZone::createTimeZone(*usTimezone)), ec);
573
574     if (!U_SUCCESS(ec)) {
575         LOGE("Can't create cal: %d, %s", ec, u_errorName(ec));
576         throw Common::UnknownException("Can't create cal");
577     }
578     UDate date = m_calendar->getTime(ec);
579     if (!U_SUCCESS(ec)) {
580         LOGE("Can't get time of m_calendar: %d, %s", ec, u_errorName(ec));
581         throw Common::UnknownException("Can't get time of m_calendar");
582     }
583     cal->setTime(date, ec);
584     if (!U_SUCCESS(ec)) {
585         LOGE("Can't get time of cal: %d, %s", ec, u_errorName(ec));
586         throw Common::UnknownException("Can't get time of cal");
587     }
588     return cal;
589 }
590
591 icu::Calendar* TZDate::getUTCCalendar() const {
592     UErrorCode ec = U_ZERO_ERROR;
593     icu::Calendar *cal = Calendar::createInstance(*(TimeZone::getGMT()), ec);
594
595     if (!U_SUCCESS(ec)) {
596         LOGE("Can't create cal: %d, %s", ec, u_errorName(ec));
597         throw Common::UnknownException("Can't create cal");
598     }
599     UDate date = m_calendar->getTime(ec);
600     if (!U_SUCCESS(ec)) {
601         LOGE("Can't get time of m_calendar: %d, %s", ec, u_errorName(ec));
602         throw Common::UnknownException("Can't get time of m_calendar");
603     }
604     cal->setTime(date, ec);
605     if (!U_SUCCESS(ec)) {
606         LOGE("Can't get time of cal: %d, %s", ec, u_errorName(ec));
607         throw Common::UnknownException("Can't get time of cal");
608     }
609     return cal;
610 }
611
612 void TZDate::setTimezone(const std::string& timezone, bool timezone_is_certain) {
613     if (!timezone_is_certain) {
614         timezone_is_certain = TimeUtilTools::isInTimezonesArray(timezone);
615     }
616
617     if (timezone_is_certain) {
618         std::shared_ptr<UnicodeString> usTimezone(TimeUtilTools::toUnicodeString(timezone));
619         TimeZone* tz = TimeZone::createTimeZone(*usTimezone);
620         m_calendar->adoptTimeZone(tz);
621     }
622     else {
623         LOGD("Invalid timezone");
624     }
625 }
626
627 #ifdef IMPL_BACKWARD_COMPATIBLE
628 TZDate::TZDate(const std::string &timezone)
629 {
630     LOGD("entered");
631
632     UErrorCode ec = U_ZERO_ERROR;
633     TimeUtilTools util;
634     TimeZone *tz = util.makeTimeZone(timezone);
635     if (isAvailableTimezone(tz)) {
636         m_calendar= Calendar::createInstance(tz ,ec);
637     } else {
638         if (tz) {
639             delete tz;
640         }
641         m_calendar = Calendar::createInstance(ec);
642     }
643
644     if (U_SUCCESS(ec)) {
645         util.printDate(m_calendar);
646     } else {
647         LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
648         m_calendar = NULL;
649     }
650
651 }
652
653 TZDate::TZDate(const TZDateProperties &properties)
654 {
655     LOGD("entered");
656
657     TimeUtilTools util;
658     m_calendar= _makeCalendar(properties);
659 }
660
661 TZDate::TZDate(const std::string &dateString, const double milliseconds, const std::string &timezone)
662 {
663     m_calendar = NULL;
664
665     UErrorCode ec = U_ZERO_ERROR;
666     Calendar *dateCalender = Calendar::createInstance(ec);
667     DateFormat *df = NULL;
668     try {
669         if (dateCalender == NULL || U_FAILURE(ec)) {
670             ThrowMsg(Commons::UnknownException, "Can't make calendar");
671         }
672         df = new SimpleDateFormat("EEE MMM d uuuuuu HH:mm:ss", Locale::getEnglish(), ec);
673
674         if (df == NULL || U_FAILURE(ec)) {
675             ThrowMsg(Commons::UnknownException, "Can't make DateFormat");
676         }
677         ParsePosition pos;
678         pos.setIndex(0);
679         TimeUtilTools util;
680         UnicodeString text(dateString.c_str());
681         UDate date = df->parse(text, ec);
682
683         if (U_FAILURE(ec)) {
684             ThrowMsg(Commons::UnknownException, "parse fail");
685         }
686
687         dateCalender->setTime(date, ec);
688
689         if (U_FAILURE(ec)) {
690             ThrowMsg(Commons::UnknownException, "setTime fail");
691         }
692
693         util.printDate(dateCalender);
694         TZDateProperties properties;
695         properties.year = _get(TZDATE_YEAR, dateCalender);
696         properties.month = _get(TZDATE_MONTH, dateCalender);
697         properties.day = _get(TZDATE_DATE, dateCalender);
698         properties.hours = _get(TZDATE_HOUR_OF_DAY, dateCalender);
699         properties.minutes = _get(TZDATE_MINUTE, dateCalender);
700         properties.seconds = _get(TZDATE_SECOND, dateCalender);
701         properties.milliseconds = milliseconds;
702         properties.timezone = timezone;
703         m_calendar = _makeCalendar(properties);
704     } catch (const WrtDeviceApis::Commons::Exception& err) {
705         LOGE("%s : %s", err.GetClassName().c_str(), err.GetMessage().c_str());
706         if (m_calendar) {
707             delete m_calendar;
708         }
709         m_calendar = NULL;
710     }
711
712     if (dateCalender) {
713         delete dateCalender;
714     }
715     if (df) {
716         delete df;
717     }
718 }
719
720
721 bool TZDate::isAvailableTimezone(const std::string &timezone)
722 {
723     TimeUtilTools util;
724     TimeZone *tz = util.makeTimeZone(timezone);
725
726     bool result = isAvailableTimezone(tz);
727     
728     if (tz) {
729         delete tz;
730     }
731     return result;
732 }
733
734 bool TZDate::isAvailableTimezone(TimeZone *tz) {
735     TimeUtilTools util;
736     bool result = true;
737     UnicodeString id;
738     tz->getID(id);
739
740     if (util.toString(id) == "Etc/Unknown") {
741         result = false;
742     }
743
744     return result;
745 }
746
747 std::string TZDate::_getTimezoneName(Calendar *cal)
748 {
749     if (cal == NULL) {
750         ThrowMsg(Commons::UnknownException, "Invalid Date");
751     }
752
753     UnicodeString id;
754     TimeUtilTools util;
755
756     cal->getTimeZone().getID(id);
757     std::string s_result = util.toString(id);
758     LOGD("%s", s_result.c_str());
759     return s_result;
760 }
761
762 double TZDate::getTime() {
763     LOGD("entered");
764     if (m_calendar== NULL) {
765         LOGE("calendar is NULL");
766         ThrowMsg(Commons::UnknownException, "Invalid Date");
767     }
768
769     UErrorCode ec = U_ZERO_ERROR;
770
771     UDate date = m_calendar->getTime(ec);
772     if (U_SUCCESS(ec)) {
773         return static_cast<double>(date);
774     } else {
775         LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
776     }
777
778     ThrowMsg(Commons::PlatformException, "can't get time");
779 }
780
781 bool TZDate::setTime(const double time) {
782     LOGD("entered");
783     if (m_calendar == NULL)
784         ThrowMsg(Commons::UnknownException, "Invalid Date");
785
786     UErrorCode ec = U_ZERO_ERROR;
787
788     m_calendar->setTime(static_cast<UDate>(time), ec);
789     if (U_SUCCESS(ec)) {
790         return true;
791     } else {
792         LOGE("Failed to set time: %d, %s", ec, u_errorName(ec));
793     }
794
795     return false;
796 }
797
798 Calendar *TZDate::_makeCalendar(const TZDateProperties &properties)
799 {
800     LOGD("entered");
801     UErrorCode ec = U_ZERO_ERROR;
802     TimeUtilTools util;
803
804     Calendar *cal = NULL;
805     if ((properties.timezone == "") || !isAvailableTimezone(properties.timezone)) {
806         cal = Calendar::createInstance(ec);
807     } else {
808         cal = Calendar::createInstance(util.makeTimeZone(properties.timezone) ,ec);
809     }
810
811     if ((cal != NULL) && U_SUCCESS(ec)) {
812         try {
813             cal->set(UCAL_DATE, 10); //set specific date because first date(1) or last date(31) can make changing of month because of timezone
814     
815             _set(TZDATE_YEAR, properties.year, cal);
816             _set(TZDATE_MONTH, properties.month, cal);
817             _set(TZDATE_DATE, properties.day, cal);
818             _set(TZDATE_HOUR_OF_DAY, properties.hours, cal);
819             _set(TZDATE_MINUTE, properties.minutes, cal);
820             _set(TZDATE_SECOND, properties.seconds, cal);
821             _set(TZDATE_MILLISECOND, properties.milliseconds, cal);
822         } catch (const WrtDeviceApis::Commons::Exception& err) {
823             LOGE("%s : %s ", err.GetClassName().c_str(), err.GetMessage().c_str());
824             if (cal) {
825                 delete cal;
826             }
827             cal = NULL;
828         }
829         return cal;
830     } else {
831         LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
832     }
833
834     if (cal) {
835         delete cal;
836     }
837     return NULL;
838 }
839
840
841 long TZDate::_get(const TZDateFields field, Calendar *cal)
842 {
843     LOGD("<<<");
844
845     if (cal == NULL) {
846         ThrowMsg(Commons::UnknownException, "Invalid Date");
847     }
848
849     if (_convertDateField(field) == UCAL_FIELD_COUNT) {
850         LOGD(">>> UCAL_FIELD_COUNT");
851         return -1;
852     }
853
854     UErrorCode ec = U_ZERO_ERROR;
855     TimeUtilTools util;
856     int32_t value = cal->get(_convertDateField(field), ec);
857     if (U_SUCCESS(ec)) {
858         long result = util.tolong(value);
859
860         LOGD(">>> result: %ld", result);
861         return result;
862     }
863     LOGE("Failed to get calendar: %d, %s", ec, u_errorName(ec));
864     ThrowMsg(Commons::PlatformException, "Can't get Calendar value");
865 }
866
867 long TZDate::get(const TZDateFields field)
868 {
869     LOGD("<<<");
870
871     long result = _get(field, m_calendar);
872     if (field == TZDATE_DAY_OF_WEEK)
873         result--;
874     return result;
875 }
876
877
878 void TZDate::_set(const TZDateFields field, const long value, Calendar *cal)
879 {
880     if (_convertDateField(field) == UCAL_FIELD_COUNT) {
881         return;
882     }
883
884     if (cal == NULL) {
885         ThrowMsg(Commons::UnknownException, "Invalid Date");
886     }
887
888     TimeUtilTools util;
889     Calendar *originCal = cal->clone();
890     cal->set(_convertDateField(field), util.toint32_t(value));
891     
892     LOGD("Field : %d, value : %ld, result: %d", field, value, _get(field, cal));
893     try {
894         if (field == TZDATE_YEAR) {
895             if (value != _get(field, cal))
896                 ThrowMsg(Commons::PlatformException, "Out of range");
897         } else if (field == TZDATE_MONTH) {
898             long yearDiff = value / 12;
899             long month = value % 12;
900             if (value < 0) {
901                 yearDiff--;
902                 month += 12;
903             }
904             
905             long originYear = _get(TZDATE_YEAR, originCal);
906             if (((originYear + yearDiff) != _get(TZDATE_YEAR, cal))
907                 || (month != _get(TZDATE_MONTH, cal))) {
908                 LOGD("originYear: %ld, yearDiff: %ld, TZDATE_YEAR: %ld", originYear, yearDiff, _get(TZDATE_YEAR, cal));
909                 LOGD(" month: %ld, TZDATE_MONTH: %ld", month, _get(TZDATE_MONTH, cal));
910                 ThrowMsg(Commons::PlatformException, "Out of range");
911             }
912         } else {
913             UErrorCode ec = U_ZERO_ERROR;
914             double diff = value - _get(field, originCal);
915             if (field == TZDATE_DATE)
916                 diff *= U_MILLIS_PER_DAY;
917             else if (field == TZDATE_HOUR_OF_DAY)
918                 diff *= U_MILLIS_PER_HOUR;
919             else if (field == TZDATE_MINUTE)
920                 diff *= U_MILLIS_PER_MINUTE;
921             else if (field == TZDATE_SECOND)
922                 diff *= U_MILLIS_PER_SECOND;
923         
924             UDate originUDate = originCal->getTime(ec);
925             if (!U_SUCCESS(ec)) {
926                 LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
927                 ThrowMsg(Commons::PlatformException, "ICU Error");
928             }
929
930             LOGD("originUDate : %f, diff : %ld", (double)originUDate, diff);
931
932             if ((U_DATE_MAX - originUDate) < diff)
933                 ThrowMsg(Commons::PlatformException, "Out of range");
934         }
935     } catch (Commons::PlatformException& err) {
936         LOGE("%s", err.GetMessage().c_str());
937         if (originCal)
938             delete originCal;
939         throw(err);
940     }
941     if (originCal) {
942         delete originCal;
943     }
944 }
945
946 void TZDate::set(const TZDateFields field, const long value)
947 {
948     try {
949         _set(field, value, m_calendar);
950     } catch (Commons::PlatformException& err) {
951         LOGE("%s", err.GetMessage().c_str());
952         if (m_calendar) {
953             delete m_calendar;
954         }
955         m_calendar = NULL;
956     }
957 }
958
959 TZDateProperties TZDate::_makeProperties(Calendar *cal)
960 {
961     TZDateProperties result;
962     TimeUtilTools util;
963
964     result.year = _get(TZDATE_YEAR, cal);
965     result.month = _get(TZDATE_MONTH,cal);
966     result.day = _get(TZDATE_DATE, cal);
967     result.hours = _get(TZDATE_HOUR_OF_DAY, cal);
968     result.minutes = _get(TZDATE_MINUTE, cal);
969     result.seconds = _get(TZDATE_SECOND, cal);
970     result.milliseconds = _get(TZDATE_MILLISECOND, cal);
971     result.timezone=  _getTimezoneName(cal);
972
973     return result;
974 }
975
976 TZDateProperties TZDate::makeProperties()
977 {
978     return _makeProperties(m_calendar);
979 }
980
981
982
983 const UCalendarDateFields TZDate::_convertDateField(const TZDateFields field)
984 {
985     switch (field) {
986     case TZDATE_ERA:
987         return UCAL_ERA;
988         break;
989     case TZDATE_YEAR:
990         return UCAL_EXTENDED_YEAR;
991         break;
992     case TZDATE_MONTH:
993         return UCAL_MONTH;
994         break;
995     case TZDATE_WEEK_OF_YEAR:
996         return UCAL_WEEK_OF_YEAR;
997         break;
998     case TZDATE_WEEK_OF_MONTH:
999         return UCAL_WEEK_OF_MONTH;
1000         break;
1001     case TZDATE_DATE:
1002         return UCAL_DATE;
1003         break;
1004     case TZDATE_DAY_OF_YEAR:
1005         return UCAL_DAY_OF_YEAR;
1006         break;
1007     case TZDATE_DAY_OF_WEEK:
1008         return UCAL_DAY_OF_WEEK;
1009         break;
1010     case TZDATE_DAY_OF_WEEK_IN_MONTH:
1011         return UCAL_DAY_OF_WEEK_IN_MONTH;
1012         break;
1013     case TZDATE_AM_PM:
1014         return UCAL_AM_PM;
1015         break;
1016     case TZDATE_HOUR:
1017         return UCAL_HOUR;
1018         break;
1019     case TZDATE_HOUR_OF_DAY:
1020         return UCAL_HOUR_OF_DAY;
1021         break;
1022     case TZDATE_MINUTE:
1023         return UCAL_MINUTE;
1024         break;
1025     case TZDATE_SECOND:
1026         return UCAL_SECOND;
1027         break;
1028     case TZDATE_MILLISECOND:
1029         return UCAL_MILLISECOND;
1030         break;
1031     case TZDATE_ZONE_OFFSET:
1032         return UCAL_ZONE_OFFSET;
1033         break;
1034     case TZDATE_DST_OFFSET:
1035         return UCAL_DST_OFFSET;
1036         break;
1037     default:
1038         return UCAL_FIELD_COUNT;
1039     }
1040 }
1041
1042 #endif // IMPL_BACKWARD_COMPATIBLE
1043
1044
1045 } // Time
1046 } // DeviceAPI