2 // Tizen Web Device API
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <Commons/Exception.h>
19 #include <unicode/timezone.h>
20 #include <unicode/vtzone.h>
21 #include <unicode/smpdtfmt.h>
23 #include "TimeUtilTools.h"
26 using namespace WrtDeviceApis;
31 TZDate::TZDate(const bool isNotNull)
35 if (isNotNull == FALSE) {
38 UErrorCode ec = U_ZERO_ERROR;
40 myCalendar = Calendar::createInstance(ec);
43 util.printDate(myCalendar);
47 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
52 TZDate::TZDate(const std::string &timezone)
56 UErrorCode ec = U_ZERO_ERROR;
58 myCalendar = Calendar::createInstance(util.makeTimeZone(timezone) ,ec);
62 util.printDate(myCalendar);
63 if (!util.compareTimeZoneName(myCalendar, timezone)) {
65 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
69 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
74 TZDate::TZDate(const TZDateProperties &properties)
79 myCalendar = _makeCalendar(properties);
80 if (myCalendar != NULL) {
81 if (!util.compareTimeZoneName(myCalendar, properties.timezone)) {
84 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
87 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
94 if (myCalendar != NULL)
100 bool TZDate::isNull()
102 if (myCalendar == NULL)
108 Calendar *TZDate::_makeCalendar(const TZDateProperties &properties)
111 UErrorCode ec = U_ZERO_ERROR;
114 Calendar *cal = NULL;
115 if (properties.timezone == "")
116 cal = Calendar::createInstance(ec);
118 cal = Calendar::createInstance(util.makeTimeZone(properties.timezone) ,ec);
120 if ((cal != NULL) && U_SUCCESS(ec)) {
121 cal->set(util.toint32_t(properties.year), util.toint32_t(properties.month),
122 util.toint32_t(properties.day), util.toint32_t(properties.hours), util.toint32_t(properties.minutes), util.toint32_t(properties.seconds));
123 cal->set(UCAL_MILLISECOND, util.toint32_t(properties.milliseconds));
130 std::string TZDate::_getTimezoneName(Calendar *cal)
135 cal->getTimeZone().getID(id);
136 std::string s_result = util.toString(id);
141 const UCalendarDateFields TZDate::_convertDateField(const TZDateFields field)
153 case TZDATE_WEEK_OF_YEAR:
154 return UCAL_WEEK_OF_YEAR;
156 case TZDATE_WEEK_OF_MONTH:
157 return UCAL_WEEK_OF_MONTH;
162 case TZDATE_DAY_OF_YEAR:
163 return UCAL_DAY_OF_YEAR;
165 case TZDATE_DAY_OF_WEEK:
166 return UCAL_DAY_OF_WEEK;
168 case TZDATE_DAY_OF_WEEK_IN_MONTH:
169 return UCAL_DAY_OF_WEEK_IN_MONTH;
177 case TZDATE_HOUR_OF_DAY:
178 return UCAL_HOUR_OF_DAY;
186 case TZDATE_MILLISECOND:
187 return UCAL_MILLISECOND;
189 case TZDATE_ZONE_OFFSET:
190 return UCAL_ZONE_OFFSET;
192 case TZDATE_DST_OFFSET:
193 return UCAL_DST_OFFSET;
196 return UCAL_FIELD_COUNT;
200 TZDateProperties TZDate::_makeProperties(Calendar *cal)
202 TZDateProperties result;
205 result.year = _get(TZDATE_YEAR, cal);
206 result.month = _get(TZDATE_MONTH,cal);
207 result.day = _get(TZDATE_DATE, cal);
208 result.hours = _get(TZDATE_HOUR_OF_DAY, cal);
209 result.minutes = _get(TZDATE_MINUTE, cal);
210 result.seconds = _get(TZDATE_SECOND, cal);
211 result.milliseconds = _get(TZDATE_MILLISECOND, cal);
212 result.timezone= _getTimezoneName(cal);
217 TZDateProperties TZDate::makeProperties() {
218 return _makeProperties(myCalendar);
221 std::string TZDate::getTimezone()
223 return _getTimezoneName(myCalendar);
226 TZDateProperties TZDate::toTimezone(const std::string timezone) {
228 Calendar *newCalendar = myCalendar->clone();
229 newCalendar->setTimeZone(*(util.makeTimeZone(timezone)));
231 if (!util.compareTimeZoneName(newCalendar, timezone)) {
233 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
236 TZDateProperties newProps = _makeProperties(newCalendar);
242 long TZDate::_get(const TZDateFields field, Calendar *cal)
246 if (_convertDateField(field) == UCAL_FIELD_COUNT){
247 LoggerD(">>> UCAL_FIELD_COUNT");
251 UErrorCode ec = U_ZERO_ERROR;
253 int32_t value = cal->get(_convertDateField(field), ec);
255 long result = util.tolong(value);
257 LoggerD(">>> result:" << result);
260 ThrowMsg(Commons::PlatformException, "Can't get Calendar value");
262 long TZDate::get(const TZDateFields field)
266 long result = _get(field, myCalendar);
267 if (field == TZDATE_DAY_OF_WEEK)
272 void TZDate::set(const TZDateFields field, const long value)
274 if (_convertDateField(field) == UCAL_FIELD_COUNT)
278 myCalendar->set(_convertDateField(field), util.toint32_t(value));
279 LoggerD("Field : " << field << " value : " << get(field));
282 long TZDate::getUTC(const TZDateFields field)
284 if (_convertDateField(field) == UCAL_FIELD_COUNT)
287 UErrorCode ec = U_ZERO_ERROR;
290 Calendar *utcCalendar = myCalendar->clone();
291 utcCalendar->setTimeZone(*(TimeZone::getGMT()));
293 int32_t value = utcCalendar->get(_convertDateField(field), ec);
297 long result = util.tolong(value);
298 if (field == TZDATE_DAY_OF_WEEK)
300 LoggerD("result : " << result);
305 ThrowMsg(Commons::PlatformException, "Can't get UTC Calendar value");
308 void TZDate::setUTC(const TZDateFields field, const long value)
310 if (_convertDateField(field) == UCAL_FIELD_COUNT)
314 UErrorCode ec = U_ZERO_ERROR;
316 long myValue = get(field);
317 long utcValue = getUTC(field);
318 if (field == TZDATE_DAY_OF_WEEK)
320 set(field, myValue + value - utcValue);
323 ThrowMsg(Commons::PlatformException, "Can't set UTC Calendar value");
326 long long TZDate::difference(const TZDateProperties &prop) {
330 UErrorCode ec = U_ZERO_ERROR;
332 Calendar *otherCalendar = _makeCalendar(prop);
334 if (!util.compareTimeZoneName(otherCalendar, prop.timezone)) {
335 delete otherCalendar;
336 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
339 UDate myTime = myCalendar->getTime(ec);
342 UDate otherTime = otherCalendar->getTime(ec);
344 LoggerD("myCalendar");
345 util.printDate(myCalendar);
346 LoggerD("otherCalendar");
347 util.printDate(otherCalendar);
348 delete otherCalendar;
350 LoggerD("myTime : " <<myTime);
351 LoggerD("otherTime : " << otherTime);
353 return static_cast<long long>(myTime - otherTime);
356 delete otherCalendar;
357 ThrowMsg(Commons::PlatformException, "Calendar error in difference");
360 TZDateProperties TZDate::addDuration(const DurationProperties &duration) {
362 UErrorCode ec = U_ZERO_ERROR;
366 Calendar *cal = myCalendar->clone();
367 long long length = duration.length;
368 short unit = duration.unit;
369 int msec=0, sec=0, min=0, hour=0;
372 if (unit == MSECS_UNIT) {
373 msec = length % 1000;
377 if ((length != 0) && (unit == SECONDS_UNIT)) {
382 if ((length != 0) && (unit == MINUTES_UNIT)) {
387 if ((length != 0) && (unit == HOURS_UNIT)) {
393 LoggerD("day:"<<day<<" hour:"<<hour<<" min:"<<min<<" sec:"<<sec<<" msec:"<<msec);
396 cal->add(UCAL_MILLISECOND, util.toint32_t(msec), ec);
398 Throw(Commons::PlatformException);
401 cal->add(UCAL_SECOND, util.toint32_t(sec), ec);
403 Throw(Commons::PlatformException);
406 cal->add(UCAL_MINUTE, util.toint32_t(min), ec);
408 Throw(Commons::PlatformException);
411 cal->add(UCAL_HOUR_OF_DAY, util.toint32_t(hour), ec);
413 Throw(Commons::PlatformException);
416 UDate oldValue = cal->getTime(ec);
418 Throw(Commons::PlatformException);
421 LoggerD("1st day : " << day);
426 else if (day > INT_MAX)
432 LoggerD("amount : " << amount);
433 LoggerD("2nd day : " << day);
434 cal->add(UCAL_DATE, util.toint32_t(amount), ec);
436 Throw(Commons::PlatformException);
438 UDate newValue = cal->getTime(ec);
440 Throw(Commons::PlatformException);
442 int diff = static_cast<int>((newValue - oldValue) / 24 / 60 / 60 / 1000);
443 LoggerD("diff : " << diff);
444 if (diff != amount) {
445 Throw(Commons::OutOfRangeException);
449 } catch (Commons::PlatformException) {
451 ThrowMsg(Commons::PlatformException, "Calendar error in addDuration");
452 } catch (Commons::OutOfRangeException) {
454 ThrowMsg(Commons::OutOfRangeException, "The result is beyond the scope that TZDate can handle.");
457 TZDateProperties result = _makeProperties(cal);
462 ThrowMsg(Commons::PlatformException, "Calendar error in addDuration");
466 std::string TZDate::getUTCTimezoneName() {
470 TimeZone::getGMT()->getID(id);
471 std::string s_result = util.toString(id);
476 std::string TZDate::getLocalTimezoneName() {
480 TimeZone::createDefault()->getID(id);
481 std::string s_result = util.toString(id);
486 double TZDate::getTime() {
488 UErrorCode ec = U_ZERO_ERROR;
490 UDate date = myCalendar->getTime(ec);
492 return static_cast<double>(date);
494 ThrowMsg(Commons::PlatformException, "can't get time");
497 bool TZDate::setTime(const double time) {
499 UErrorCode ec = U_ZERO_ERROR;
501 myCalendar->setTime(static_cast<UDate>(time), ec);
508 std::string TZDate::toDateString(bool bLocale) {
509 UErrorCode ec = U_ZERO_ERROR;
513 DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::DATE_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
515 fmt->setCalendar(*myCalendar);
516 fmt->format(myCalendar->getTime(ec), str);
520 std::string result = util.toString(str);
528 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
531 std::string TZDate::toTimeString(bool bLocale) {
532 UErrorCode ec = U_ZERO_ERROR;
536 DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::TIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
538 fmt->setCalendar(*myCalendar);
539 fmt->format(myCalendar->getTime(ec), str);
543 std::string result = util.toString(str);
550 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
553 std::string TZDate::toString(bool bLocale) {
556 UErrorCode ec = U_ZERO_ERROR;
560 DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::DATETIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
562 fmt->setCalendar(*myCalendar);
563 fmt->format(myCalendar->getTime(ec), str);
567 std::string result = util.toString(str);
573 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
576 std::string TZDate::getTimezoneAbbreviation() {
579 UErrorCode ec = U_ZERO_ERROR;
583 DateFormat *fmt = new SimpleDateFormat(UnicodeString("V"), Locale::getEnglish(), ec);
585 fmt->setCalendar(*myCalendar);
586 fmt->format(myCalendar->getTime(ec), str);
590 std::string result = util.toString(str);
598 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
601 long TZDate::secondsFromUTC() {
603 UErrorCode ec = U_ZERO_ERROR;
606 int32_t zoneOffset = myCalendar->get(UCAL_ZONE_OFFSET, ec);
608 ThrowMsg(Commons::PlatformException, "can't get zone offset");
610 int32_t dstOffset = myCalendar->get(UCAL_DST_OFFSET, ec);
612 ThrowMsg(Commons::PlatformException, "can't get dst offset");
614 long result = -((util.tolong(zoneOffset + dstOffset)) / MILLISTOSEC);
616 LoggerD("result : " << result);
620 bool TZDate::isDST() {
622 UErrorCode ec = U_ZERO_ERROR;
624 UBool result = myCalendar->inDaylightTime(ec);
627 ThrowMsg(Commons::PlatformException, "can't inDaylightTime value from ICU");
629 return static_cast<bool>(result);
632 TZDateProperties TZDate::getDSTTransition(DSTTransition trans) {
635 UErrorCode ec = U_ZERO_ERROR;
636 TZDateProperties props;
637 UDate dstTransitionDate = myCalendar->getTime(ec);
638 UBool result = false;
641 UnicodeString *id = util.toUnicodeString(getTimezone());
643 VTimeZone *vtz = VTimeZone::createVTimeZoneByID(*id);
646 TimeZoneTransition tzTrans;
647 if (vtz->useDaylightTime() == TRUE) {
648 if (trans == NEXT_TRANSITION)
649 result = vtz->getNextTransition(dstTransitionDate, FALSE, tzTrans);
651 result = vtz->getPreviousTransition(dstTransitionDate, FALSE, tzTrans);
652 if (result == TRUE) {
653 LoggerD("result is TRUE");
654 dstTransitionDate = tzTrans.getTime();
662 Calendar *dstTransCalendar = myCalendar->clone();
663 dstTransCalendar->setTime(dstTransitionDate, ec);
665 props = _makeProperties(dstTransCalendar);
666 delete dstTransCalendar;
669 delete dstTransCalendar;
671 ThrowMsg(Commons::PlatformException, "can't getDSTTransition value from ICU");