2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <dpl/log/log.h>
22 #include <Commons/Exception.h>
24 #include <unicode/timezone.h>
25 #include <unicode/vtzone.h>
26 #include <unicode/smpdtfmt.h>
29 #include "TimeUtilTools.h"
31 using namespace TizenApis::Api::TimeUtil;
32 using namespace WrtDeviceApis;
38 TZDate::TZDate(const bool isNotNull)
42 if (isNotNull == FALSE) {
45 UErrorCode ec = U_ZERO_ERROR;
47 myCalendar = Calendar::createInstance(ec);
50 util.printDate(myCalendar);
54 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
59 TZDate::TZDate(const std::string &timezone)
63 UErrorCode ec = U_ZERO_ERROR;
65 myCalendar = Calendar::createInstance(util.makeTimeZone(timezone) ,ec);
69 util.printDate(myCalendar);
70 if (!util.compareTimeZoneName(myCalendar, timezone)) {
72 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
76 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
81 TZDate::TZDate(const TZDateProperties &properties)
86 myCalendar = _makeCalendar(properties);
87 if (!util.compareTimeZoneName(myCalendar, properties.timezone)) {
89 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
92 if (myCalendar != NULL) {
93 util.printDate(myCalendar);
95 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
103 if (myCalendar != NULL)
109 bool TZDate::isNull()
111 if (myCalendar == NULL)
117 Calendar *TZDate::_makeCalendar(const TZDateProperties &properties)
120 UErrorCode ec = U_ZERO_ERROR;
123 Calendar *cal = NULL;
124 if (properties.timezone == "")
125 cal = Calendar::createInstance(ec);
127 cal = Calendar::createInstance(util.makeTimeZone(properties.timezone) ,ec);
129 if ((cal != NULL) && U_SUCCESS(ec)) {
130 cal->set(util.toint32_t(properties.year), util.toint32_t(properties.month),
131 util.toint32_t(properties.day), util.toint32_t(properties.hours), util.toint32_t(properties.minutes), util.toint32_t(properties.seconds));
132 cal->set(UCAL_MILLISECOND, util.toint32_t(properties.milliseconds));
139 std::string TZDate::_getTimezoneName(Calendar *cal)
144 cal->getTimeZone().getID(id);
145 std::string s_result = util.toString(id);
150 const UCalendarDateFields TZDate::_convertDateField(const TZDateFields field)
162 case TZDATE_WEEK_OF_YEAR:
163 return UCAL_WEEK_OF_YEAR;
165 case TZDATE_WEEK_OF_MONTH:
166 return UCAL_WEEK_OF_MONTH;
171 case TZDATE_DAY_OF_YEAR:
172 return UCAL_DAY_OF_YEAR;
174 case TZDATE_DAY_OF_WEEK:
175 return UCAL_DAY_OF_WEEK;
177 case TZDATE_DAY_OF_WEEK_IN_MONTH:
178 return UCAL_DAY_OF_WEEK_IN_MONTH;
186 case TZDATE_HOUR_OF_DAY:
187 return UCAL_HOUR_OF_DAY;
195 case TZDATE_MILLISECOND:
196 return UCAL_MILLISECOND;
198 case TZDATE_ZONE_OFFSET:
199 return UCAL_ZONE_OFFSET;
201 case TZDATE_DST_OFFSET:
202 return UCAL_DST_OFFSET;
205 return UCAL_FIELD_COUNT;
209 TZDateProperties TZDate::_makeProperties(Calendar *cal)
211 TZDateProperties result;
214 result.year = _get(TZDATE_YEAR, cal);
215 result.month = _get(TZDATE_MONTH,cal);
216 result.day = _get(TZDATE_DATE, cal);
217 result.hours = _get(TZDATE_HOUR_OF_DAY, cal);
218 result.minutes = _get(TZDATE_MINUTE, cal);
219 result.seconds = _get(TZDATE_SECOND, cal);
220 result.milliseconds = _get(TZDATE_MILLISECOND, cal);
221 result.timezone= _getTimezoneName(cal);
226 std::string TZDate::getTimezone()
228 return _getTimezoneName(myCalendar);
231 TZDateProperties TZDate::toTimezone(const std::string timezone) {
233 Calendar *newCalendar = myCalendar->clone();
234 newCalendar->setTimeZone(*(util.makeTimeZone(timezone)));
236 if (!util.compareTimeZoneName(newCalendar, timezone)) {
238 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
241 TZDateProperties newProps = _makeProperties(newCalendar);
247 long TZDate::_get(const TZDateFields field, Calendar *cal)
251 if (_convertDateField(field) == UCAL_FIELD_COUNT){
252 LogDebug(">>> UCAL_FIELD_COUNT");
256 UErrorCode ec = U_ZERO_ERROR;
258 int32_t value = cal->get(_convertDateField(field), ec);
260 long result = util.tolong(value);
262 LogDebug(">>> result:" << result);
265 ThrowMsg(Commons::PlatformException, "Can't get Calendar value");
268 long TZDate::get(const TZDateFields field)
272 long result = _get(field, myCalendar);
273 if (field == TZDATE_DAY_OF_WEEK)
278 void TZDate::set(const TZDateFields field, const long value)
280 if (_convertDateField(field) == UCAL_FIELD_COUNT)
284 myCalendar->set(_convertDateField(field), util.toint32_t(value));
285 LogDebug("Field : " << field << " value : " << get(field));
288 long TZDate::getUTC(const TZDateFields field)
290 if (_convertDateField(field) == UCAL_FIELD_COUNT)
293 UErrorCode ec = U_ZERO_ERROR;
296 Calendar *utcCalendar = myCalendar->clone();
297 utcCalendar->setTimeZone(*(TimeZone::getGMT()));
299 int32_t value = utcCalendar->get(_convertDateField(field), ec);
303 long result = util.tolong(value);
304 if (field == TZDATE_DAY_OF_WEEK)
306 LogDebug("result : " << result);
311 ThrowMsg(Commons::PlatformException, "Can't get UTC Calendar value");
315 void TZDate::setUTC(const TZDateFields field, const long value)
317 if (_convertDateField(field) == UCAL_FIELD_COUNT)
321 UErrorCode ec = U_ZERO_ERROR;
323 long myValue = get(field);
324 long utcValue = getUTC(field);
325 if (field == TZDATE_DAY_OF_WEEK)
327 set(field, myValue + value - utcValue);
330 ThrowMsg(Commons::PlatformException, "Can't set UTC Calendar value");
333 long long TZDate::difference(const TZDateProperties &prop) {
337 UErrorCode ec = U_ZERO_ERROR;
339 Calendar *otherCalendar = _makeCalendar(prop);
341 if (!util.compareTimeZoneName(otherCalendar, prop.timezone)) {
342 delete otherCalendar;
343 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
346 UDate myTime = myCalendar->getTime(ec);
349 UDate otherTime = otherCalendar->getTime(ec);
351 LogDebug("myCalendar");
352 util.printDate(myCalendar);
353 LogDebug("otherCalendar");
354 util.printDate(otherCalendar);
355 delete otherCalendar;
357 LogDebug("myTime : " <<myTime);
358 LogDebug("otherTime : " << otherTime);
360 return static_cast<long long>(myTime - otherTime);
363 delete otherCalendar;
364 ThrowMsg(Commons::PlatformException, "Calendar error in difference");
368 TZDateProperties TZDate::addDuration(const DurationProperties &duration) {
370 UErrorCode ec = U_ZERO_ERROR;
374 Calendar *cal = myCalendar->clone();
375 long long length = duration.length;
376 short unit = duration.unit;
377 int msec=0, sec=0, min=0, hour=0;
380 if (unit == MSECS_UNIT) {
381 msec = length % 1000;
385 if ((length != 0) && (unit == SECONDS_UNIT)) {
390 if ((length != 0) && (unit == MINUTES_UNIT)) {
395 if ((length != 0) && (unit == HOURS_UNIT)) {
401 LogDebug("day:"<<day<<" hour:"<<hour<<" min:"<<min<<" sec:"<<sec<<" msec:"<<msec);
404 cal->add(UCAL_MILLISECOND, util.toint32_t(msec), ec);
406 Throw(Commons::PlatformException);
409 cal->add(UCAL_SECOND, util.toint32_t(sec), ec);
411 Throw(Commons::PlatformException);
414 cal->add(UCAL_MINUTE, util.toint32_t(min), ec);
416 Throw(Commons::PlatformException);
419 cal->add(UCAL_HOUR_OF_DAY, util.toint32_t(hour), ec);
421 Throw(Commons::PlatformException);
424 LogDebug("1st day : " << day);
429 else if (day > INT_MAX)
435 LogDebug("amount : " << amount);
436 LogDebug("2nd day : " << day);
437 cal->add(UCAL_DATE, util.toint32_t(amount), ec);
439 Throw(Commons::PlatformException);
441 } catch (Commons::PlatformException) {
443 ThrowMsg(Commons::PlatformException, "Calendar error in addDuration");
446 TZDateProperties result = _makeProperties(cal);
451 ThrowMsg(Commons::PlatformException, "Calendar error in addDuration");
455 TZDateProperties TZDate::toUTC() {
458 TZDateProperties result;
459 Calendar *utcCalendar = myCalendar->clone();
462 utcCalendar->setTimeZone(*(TimeZone::getGMT()));
463 result = _makeProperties(utcCalendar);
464 util.printDate(utcCalendar);
466 } catch (Commons::PlatformException) {
468 ThrowMsg(Commons::PlatformException, "Calendar error in toUTC");
474 TZDateProperties TZDate::toLocalTimezone() {
477 TZDateProperties result;
478 Calendar *localCalendar = myCalendar->clone();
481 localCalendar->setTimeZone(*(TimeZone::createDefault()));
483 result = _makeProperties(localCalendar);
484 util.printDate(localCalendar);
485 delete localCalendar;
486 } catch (Commons::PlatformException) {
487 delete localCalendar;
488 ThrowMsg(Commons::PlatformException, "Calendar error in toLocalTimezone");
493 double TZDate::getTime() {
495 UErrorCode ec = U_ZERO_ERROR;
497 UDate date = myCalendar->getTime(ec);
499 return static_cast<double>(date);
501 ThrowMsg(Commons::PlatformException, "can't get time");
505 bool TZDate::setTime(const double time) {
507 UErrorCode ec = U_ZERO_ERROR;
509 myCalendar->setTime(static_cast<UDate>(time), ec);
516 std::string TZDate::toDateString(bool bLocale) {
517 UErrorCode ec = U_ZERO_ERROR;
521 DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::DATE_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
523 fmt->setCalendar(*myCalendar);
524 fmt->format(myCalendar->getTime(ec), str);
528 std::string result = util.toString(str);
536 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
540 std::string TZDate::toTimeString(bool bLocale) {
541 UErrorCode ec = U_ZERO_ERROR;
545 DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::TIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
547 fmt->setCalendar(*myCalendar);
548 fmt->format(myCalendar->getTime(ec), str);
552 std::string result = util.toString(str);
559 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
563 std::string TZDate::toString(bool bLocale) {
566 UErrorCode ec = U_ZERO_ERROR;
570 DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::DATETIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
572 fmt->setCalendar(*myCalendar);
573 fmt->format(myCalendar->getTime(ec), str);
577 std::string result = util.toString(str);
583 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
587 std::string TZDate::getTimezoneAbbreviation() {
590 UErrorCode ec = U_ZERO_ERROR;
594 DateFormat *fmt = new SimpleDateFormat(UnicodeString("V"), Locale::getEnglish(), ec);
596 fmt->setCalendar(*myCalendar);
597 fmt->format(myCalendar->getTime(ec), str);
601 std::string result = util.toString(str);
609 ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
613 long TZDate::secondsFromUTC() {
615 UErrorCode ec = U_ZERO_ERROR;
618 int32_t zoneOffset = myCalendar->get(UCAL_ZONE_OFFSET, ec);
619 if (!U_SUCCESS(ec)) {
620 ThrowMsg(Commons::PlatformException, "can't get zone offset");
624 int32_t dstOffset = myCalendar->get(UCAL_DST_OFFSET, ec);
625 if (!U_SUCCESS(ec)) {
626 ThrowMsg(Commons::PlatformException, "can't get dst offset");
630 long result = ( util.tolong(zoneOffset + dstOffset)) / MILLISTOSEC;
632 LogDebug("result : " << result);
636 bool TZDate::isDST() {
638 UErrorCode ec = U_ZERO_ERROR;
640 UBool result = myCalendar->inDaylightTime(ec);
642 if (!U_SUCCESS(ec)) {
643 ThrowMsg(Commons::PlatformException, "can't inDaylightTime value from ICU");
647 return static_cast<bool>(result);
650 TZDateProperties TZDate::getDSTTransition(DSTTransition trans) {
653 UErrorCode ec = U_ZERO_ERROR;
654 TZDateProperties props;
655 UDate dstTransitionDate = myCalendar->getTime(ec);
656 UBool result = false;
659 UnicodeString *id = util.toUnicodeString(getTimezone());
661 VTimeZone *vtz = VTimeZone::createVTimeZoneByID(*id);
664 TimeZoneTransition tzTrans;
665 if (vtz->useDaylightTime() == TRUE) {
666 if (trans == NEXT_TRANSITION)
667 result = vtz->getNextTransition(dstTransitionDate, FALSE, tzTrans);
669 result = vtz->getPreviousTransition(dstTransitionDate, FALSE, tzTrans);
670 if (result == TRUE) {
671 LogDebug("result is TRUE");
672 dstTransitionDate = tzTrans.getTime();
680 Calendar *dstTransCalendar = myCalendar->clone();
681 dstTransCalendar->setTime(dstTransitionDate, ec);
683 props = _makeProperties(dstTransCalendar);
684 delete dstTransCalendar;
687 delete dstTransCalendar;
689 ThrowMsg(Commons::PlatformException, "can't getDSTTransition value from ICU");