Add DRAFT stubs for Vehicle plugin
[profile/ivi/wrt-plugins-tizen.git] / src / platform / Tizen / TimeUtil / TZDate.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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. 
15  */
16
17
18
19
20 #include <dpl/log/log.h>
21
22 #include <Commons/Exception.h>
23
24 #include <unicode/timezone.h>
25 #include <unicode/vtzone.h>
26 #include <unicode/smpdtfmt.h>
27
28 #include "TZDate.h"
29 #include "TimeUtilTools.h"
30
31 using namespace TizenApis::Api::TimeUtil;
32 using namespace WrtDeviceApis;
33
34 namespace TizenApis {
35 namespace Platform {
36 namespace TimeUtil {
37
38 TZDate::TZDate(const bool isNotNull)
39 {
40         LogDebug("entered");
41
42         if (isNotNull == FALSE) {
43                 myCalendar = NULL;
44         } else {
45                 UErrorCode ec = U_ZERO_ERROR;
46                 TimeUtilTools util;
47                 myCalendar = Calendar::createInstance(ec);
48
49                 if (U_SUCCESS(ec)) {
50                         util.printDate(myCalendar);
51                 }
52                 else {
53                         myCalendar = NULL;
54                         ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
55                 }
56         }
57 }
58
59 TZDate::TZDate(const std::string &timezone)
60 {
61         LogDebug("entered");
62
63         UErrorCode ec = U_ZERO_ERROR;
64         TimeUtilTools util;
65         myCalendar = Calendar::createInstance(util.makeTimeZone(timezone) ,ec);
66
67         if (U_SUCCESS(ec)) {
68                 TimeUtilTools util;
69                 util.printDate(myCalendar);
70                 if (!util.compareTimeZoneName(myCalendar, timezone)) {
71                         myCalendar = NULL;
72                         ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
73                 }
74         } else {
75                 myCalendar = NULL;
76                 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
77         }
78
79 }
80
81 TZDate::TZDate(const TZDateProperties &properties)
82 {
83         LogDebug("entered");
84
85         TimeUtilTools util;
86         myCalendar = _makeCalendar(properties);
87         if (!util.compareTimeZoneName(myCalendar, properties.timezone)) {
88                 myCalendar = NULL;
89                 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
90         }
91
92         if (myCalendar != NULL) {
93                 util.printDate(myCalendar);
94         } else {
95                 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
96         }
97 }
98
99 TZDate::~TZDate()
100 {
101         LogDebug("entered");
102
103         if (myCalendar != NULL)
104                 delete myCalendar;
105
106         myCalendar = NULL;
107 }
108
109 bool  TZDate::isNull()
110 {
111         if (myCalendar == NULL)
112                 return TRUE;
113
114         return FALSE;
115 }
116
117 Calendar *TZDate::_makeCalendar(const TZDateProperties &properties)
118 {
119         LogDebug("entered");
120         UErrorCode ec = U_ZERO_ERROR;
121         TimeUtilTools util;
122
123         Calendar *cal = NULL;
124         if (properties.timezone == "")
125                 cal = Calendar::createInstance(ec);
126         else
127                 cal = Calendar::createInstance(util.makeTimeZone(properties.timezone) ,ec);
128
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));
133                 return cal;
134         }
135
136         return NULL;
137 }
138
139 std::string TZDate::_getTimezoneName(Calendar *cal)
140 {
141         UnicodeString id;
142         TimeUtilTools util;
143
144         cal->getTimeZone().getID(id);
145         std::string s_result = util.toString(id);
146         LogDebug(s_result);
147         return s_result;
148 }
149
150 const UCalendarDateFields TZDate::_convertDateField(const TZDateFields field)
151 {
152         switch (field) {
153         case TZDATE_ERA:
154                 return UCAL_ERA;
155                 break;
156         case TZDATE_YEAR:
157                 return UCAL_YEAR;
158                 break;
159         case TZDATE_MONTH:
160                 return UCAL_MONTH;
161                 break;
162         case TZDATE_WEEK_OF_YEAR:
163                 return UCAL_WEEK_OF_YEAR;
164                 break;
165         case TZDATE_WEEK_OF_MONTH:
166                 return UCAL_WEEK_OF_MONTH;
167                 break;
168         case TZDATE_DATE:
169                 return UCAL_DATE;
170                 break;
171         case TZDATE_DAY_OF_YEAR:
172                 return UCAL_DAY_OF_YEAR;
173                 break;
174         case TZDATE_DAY_OF_WEEK:
175                 return UCAL_DAY_OF_WEEK;
176                 break;
177         case TZDATE_DAY_OF_WEEK_IN_MONTH:
178                 return UCAL_DAY_OF_WEEK_IN_MONTH;
179                 break;
180         case TZDATE_AM_PM:
181                 return UCAL_AM_PM;
182                 break;
183         case TZDATE_HOUR:
184                 return UCAL_HOUR;
185                 break;
186         case TZDATE_HOUR_OF_DAY:
187                 return UCAL_HOUR_OF_DAY;
188                 break;
189         case TZDATE_MINUTE:
190                 return UCAL_MINUTE;
191                 break;
192         case TZDATE_SECOND:
193                 return UCAL_SECOND;
194                 break;
195         case TZDATE_MILLISECOND:
196                 return UCAL_MILLISECOND;
197                 break;
198         case TZDATE_ZONE_OFFSET:
199                 return UCAL_ZONE_OFFSET;
200                 break;
201         case TZDATE_DST_OFFSET:
202                 return UCAL_DST_OFFSET;
203                 break;
204         default:
205                 return UCAL_FIELD_COUNT;
206         }
207 }
208
209 TZDateProperties TZDate::_makeProperties(Calendar *cal)
210 {
211         TZDateProperties result;
212         TimeUtilTools util;
213
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);
222
223         return result;
224 }
225
226 std::string TZDate::getTimezone()
227 {
228         return _getTimezoneName(myCalendar);
229 }
230
231 TZDateProperties TZDate::toTimezone(const std::string timezone) {
232         TimeUtilTools util;
233         Calendar *newCalendar = myCalendar->clone();
234         newCalendar->setTimeZone(*(util.makeTimeZone(timezone)));
235
236         if (!util.compareTimeZoneName(newCalendar, timezone)) {
237                 delete newCalendar;
238                 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
239         }
240
241         TZDateProperties newProps =  _makeProperties(newCalendar);
242         delete newCalendar;
243
244         return newProps;
245 }
246
247 long TZDate::_get(const TZDateFields field, Calendar *cal)
248 {
249         LogDebug("<<<");
250
251         if (_convertDateField(field) == UCAL_FIELD_COUNT){
252                 LogDebug(">>> UCAL_FIELD_COUNT");
253                 return -1;
254         }
255
256         UErrorCode ec = U_ZERO_ERROR;
257         TimeUtilTools util;
258         int32_t value = cal->get(_convertDateField(field), ec);
259         if (U_SUCCESS(ec)) {
260                 long result = util.tolong(value);
261
262                 LogDebug(">>> result:" << result);
263                 return result;
264         }
265         ThrowMsg(Commons::PlatformException, "Can't get Calendar value");
266         return 0;
267 }
268 long TZDate::get(const TZDateFields field)
269 {
270         LogDebug("<<<");
271
272         long result = _get(field, myCalendar);
273         if (field == TZDATE_DAY_OF_WEEK)
274                 result--;
275         return result;
276 }
277
278 void TZDate::set(const TZDateFields field, const long value)
279 {
280         if (_convertDateField(field) == UCAL_FIELD_COUNT)
281                 return;
282
283         TimeUtilTools util;
284         myCalendar->set(_convertDateField(field), util.toint32_t(value));
285         LogDebug("Field : " << field << " value : " << get(field));
286 }
287
288 long TZDate::getUTC(const TZDateFields field)
289 {
290         if (_convertDateField(field) == UCAL_FIELD_COUNT)
291                 return -1;
292
293         UErrorCode ec = U_ZERO_ERROR;
294         TimeUtilTools util;
295
296         Calendar *utcCalendar = myCalendar->clone();
297         utcCalendar->setTimeZone(*(TimeZone::getGMT()));
298
299         int32_t value = utcCalendar->get(_convertDateField(field), ec);
300         delete utcCalendar;
301
302         if (U_SUCCESS(ec)) {
303                 long result = util.tolong(value);
304                 if (field == TZDATE_DAY_OF_WEEK)
305                         result--;
306                 LogDebug("result : " << result);
307
308                 return result;
309         }
310
311         ThrowMsg(Commons::PlatformException, "Can't get UTC Calendar value");
312         return 0;
313 }
314
315 void TZDate::setUTC(const TZDateFields field, const long value)
316 {
317         if (_convertDateField(field) == UCAL_FIELD_COUNT)
318                 return;
319
320         TimeUtilTools util;
321         UErrorCode ec = U_ZERO_ERROR;
322
323         long myValue = get(field);
324         long utcValue = getUTC(field);
325         if (field == TZDATE_DAY_OF_WEEK)
326                 utcValue++;
327         set(field, myValue + value - utcValue);
328
329         if (!U_SUCCESS(ec))
330                 ThrowMsg(Commons::PlatformException, "Can't set UTC Calendar value");
331 }
332
333 long long TZDate::difference(const TZDateProperties &prop) {
334         LogDebug("entered");
335
336         TimeUtilTools util;
337         UErrorCode ec = U_ZERO_ERROR;
338
339         Calendar *otherCalendar = _makeCalendar(prop);
340
341         if (!util.compareTimeZoneName(otherCalendar, prop.timezone)) {
342                 delete otherCalendar;
343                 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
344         }
345
346         UDate myTime = myCalendar->getTime(ec);
347
348         if (U_SUCCESS(ec)) {
349                 UDate otherTime = otherCalendar->getTime(ec);
350                 if (U_SUCCESS(ec)) {
351                         LogDebug("myCalendar");
352                         util.printDate(myCalendar);
353                         LogDebug("otherCalendar");
354                         util.printDate(otherCalendar);
355                         delete otherCalendar;
356
357                         LogDebug("myTime : " <<myTime);
358                         LogDebug("otherTime : " << otherTime);
359
360                         return static_cast<long long>(myTime - otherTime);
361                 }
362         }
363         delete otherCalendar;
364         ThrowMsg(Commons::PlatformException, "Calendar error in difference");
365         return 0;
366 }
367
368 TZDateProperties TZDate::addDuration(const DurationProperties &duration) {
369         LogDebug("entered");
370         UErrorCode ec = U_ZERO_ERROR;
371
372         TimeUtilTools util;
373
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;
378         long long day=0;
379
380         if (unit == MSECS_UNIT) {
381                 msec = length % 1000;
382                 length /= 1000;
383                 unit = SECONDS_UNIT;
384         }
385         if ((length != 0) && (unit == SECONDS_UNIT)) {
386                 sec = length % 60;
387                 length /= 60;
388                 unit = MINUTES_UNIT;
389         }
390         if ((length != 0) && (unit == MINUTES_UNIT)) {
391                 min = length % 60;
392                 length /= 60;
393                 unit = HOURS_UNIT;
394         }
395         if ((length != 0) && (unit == HOURS_UNIT)) {
396                 hour = length % 24;
397                 length /= 24;
398                 unit = DAYS_UNIT;
399         }
400         day = length;
401         LogDebug("day:"<<day<<" hour:"<<hour<<" min:"<<min<<" sec:"<<sec<<" msec:"<<msec);
402         try {
403                 if (msec != 0) {
404                         cal->add(UCAL_MILLISECOND, util.toint32_t(msec), ec);
405                         if (!U_SUCCESS(ec))
406                                 Throw(Commons::PlatformException);
407                 }
408                 if (sec != 0) {
409                         cal->add(UCAL_SECOND, util.toint32_t(sec), ec);
410                         if (!U_SUCCESS(ec))
411                                 Throw(Commons::PlatformException);
412                 }
413                 if (min != 0) {
414                         cal->add(UCAL_MINUTE, util.toint32_t(min), ec);
415                         if (!U_SUCCESS(ec))
416                                 Throw(Commons::PlatformException);
417                 }
418                 if (hour != 0) {
419                         cal->add(UCAL_HOUR_OF_DAY, util.toint32_t(hour), ec);
420                         if (!U_SUCCESS(ec))
421                                 Throw(Commons::PlatformException);
422                 }
423                 while (day != 0) {
424                         LogDebug("1st day : " << day);
425                         int amount = 0;
426
427                         if (day < INT_MIN)
428                                 amount = INT_MIN;
429                         else if (day > INT_MAX)
430                                 amount = INT_MAX;
431                         else
432                                 amount = day;
433
434                         day -= amount;
435                         LogDebug("amount : " << amount);
436                         LogDebug("2nd day : " << day);
437                         cal->add(UCAL_DATE, util.toint32_t(amount), ec);
438                         if (!U_SUCCESS(ec))
439                                 Throw(Commons::PlatformException);
440                 } ;
441         } catch (Commons::PlatformException) {
442                 delete cal;
443                 ThrowMsg(Commons::PlatformException, "Calendar error in addDuration");
444         }
445
446         TZDateProperties result = _makeProperties(cal);
447         util.printDate(cal);
448         delete cal;
449
450         if (!U_SUCCESS(ec))
451                 ThrowMsg(Commons::PlatformException, "Calendar error in addDuration");
452         return result;
453 }
454
455 TZDateProperties TZDate::toUTC() {
456         LogDebug("entered");
457         TimeUtilTools util;
458         TZDateProperties result;
459         Calendar *utcCalendar = myCalendar->clone();
460
461         try {
462                 utcCalendar->setTimeZone(*(TimeZone::getGMT()));
463                 result = _makeProperties(utcCalendar);
464                 util.printDate(utcCalendar);
465                 delete utcCalendar;
466         } catch (Commons::PlatformException) {
467                 delete utcCalendar;
468                 ThrowMsg(Commons::PlatformException, "Calendar error in toUTC");
469         }
470
471         return result;
472 }
473
474 TZDateProperties TZDate::toLocalTimezone() {
475         LogDebug("entered");
476         TimeUtilTools util;
477         TZDateProperties result;
478         Calendar *localCalendar = myCalendar->clone();
479
480         try {
481                 localCalendar->setTimeZone(*(TimeZone::createDefault()));
482
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");
489         }
490         return result;  
491 }
492
493 double TZDate::getTime() {
494         LogDebug("entered");
495         UErrorCode ec = U_ZERO_ERROR;
496
497         UDate date = myCalendar->getTime(ec);
498         if (U_SUCCESS(ec))
499                 return static_cast<double>(date);
500
501         ThrowMsg(Commons::PlatformException, "can't get time");
502         return 0;
503 }
504
505 bool TZDate::setTime(const double time) {
506         LogDebug("entered");
507         UErrorCode ec = U_ZERO_ERROR;
508
509         myCalendar->setTime(static_cast<UDate>(time), ec);
510         if (U_SUCCESS(ec))
511                 return true;
512
513         return false;
514 }
515
516  std::string TZDate::toDateString(bool bLocale)  {
517         UErrorCode ec = U_ZERO_ERROR;
518         UnicodeString str;
519         TimeUtilTools util;
520
521         DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::DATE_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
522         if (U_SUCCESS(ec)) {
523                 fmt->setCalendar(*myCalendar);
524                 fmt->format(myCalendar->getTime(ec), str);
525                 delete fmt;
526
527                 if (U_SUCCESS(ec)) {
528                         std::string result = util.toString(str);
529                         str.remove();
530
531                         LogDebug (result);
532                         return result;
533                 }
534         }
535
536         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
537         return "";
538  }
539
540   std::string TZDate::toTimeString(bool bLocale)  {
541         UErrorCode ec = U_ZERO_ERROR;
542         UnicodeString str;
543         TimeUtilTools util;
544
545         DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::TIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
546         if (U_SUCCESS(ec)) {
547                 fmt->setCalendar(*myCalendar);
548                 fmt->format(myCalendar->getTime(ec), str);
549                 delete fmt;
550
551                 if (U_SUCCESS(ec)) {
552                         std::string result = util.toString(str);
553                         str.remove();
554                         LogDebug (result);
555                         return result;
556                 }
557         }
558
559         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
560         return "";
561  }
562  
563  std::string TZDate::toString(bool bLocale) {
564         LogDebug("entered");
565
566         UErrorCode ec = U_ZERO_ERROR;
567         UnicodeString str;
568         TimeUtilTools util;
569
570         DateFormat *fmt = new SimpleDateFormat(util.getDateTimeFormat(TimeUtilTools::DATETIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
571         if (U_SUCCESS(ec)) {
572                 fmt->setCalendar(*myCalendar);
573                 fmt->format(myCalendar->getTime(ec), str);
574                 delete fmt;
575
576                 if (U_SUCCESS(ec)) {
577                         std::string result = util.toString(str);
578                         str.remove();
579                         LogDebug (result);
580                         return result;
581                 }
582         }
583         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
584         return "";
585 }
586
587 std::string TZDate::getTimezoneAbbreviation() {
588         LogDebug("entered");
589
590         UErrorCode ec = U_ZERO_ERROR;
591         UnicodeString str;
592         TimeUtilTools util;
593
594         DateFormat *fmt = new SimpleDateFormat(UnicodeString("V"), Locale::getEnglish(), ec);
595         if (U_SUCCESS(ec)) {
596                 fmt->setCalendar(*myCalendar);
597                 fmt->format(myCalendar->getTime(ec), str);
598                 delete fmt;
599
600                 if (U_SUCCESS(ec)) {
601                         std::string result = util.toString(str);
602                         str.remove();
603
604                         LogDebug (result);
605
606                         return result;
607                 }
608         }
609         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
610         return "";
611 }
612
613 long TZDate::secondsFromUTC() {
614         LogDebug("entered");
615         UErrorCode ec = U_ZERO_ERROR;
616         TimeUtilTools util;
617
618         int32_t zoneOffset = myCalendar->get(UCAL_ZONE_OFFSET, ec);
619         if (!U_SUCCESS(ec)) {
620                 ThrowMsg(Commons::PlatformException, "can't get zone offset");
621                 return 0;
622         }
623
624         int32_t dstOffset = myCalendar->get(UCAL_DST_OFFSET, ec);
625         if (!U_SUCCESS(ec)) {
626                 ThrowMsg(Commons::PlatformException, "can't get dst offset");
627                 return 0;
628         }
629
630         long result = ( util.tolong(zoneOffset + dstOffset)) / MILLISTOSEC;
631
632         LogDebug("result : " << result);
633         return result;
634 }
635
636 bool TZDate::isDST() {
637         LogDebug("entered");
638         UErrorCode ec = U_ZERO_ERROR;
639         TimeUtilTools util;
640         UBool result = myCalendar->inDaylightTime(ec);
641
642         if (!U_SUCCESS(ec)) {
643                 ThrowMsg(Commons::PlatformException, "can't inDaylightTime value from ICU");
644                 return FALSE;
645         }
646
647         return static_cast<bool>(result);
648 }
649
650 TZDateProperties TZDate::getDSTTransition(DSTTransition trans) {
651         LogDebug("entered");
652         TimeUtilTools util;
653         UErrorCode ec = U_ZERO_ERROR;
654         TZDateProperties props;
655         UDate dstTransitionDate = myCalendar->getTime(ec);
656         UBool result = false;
657
658         if (U_SUCCESS(ec)) {
659                 UnicodeString *id = util.toUnicodeString(getTimezone());
660
661                 VTimeZone *vtz = VTimeZone::createVTimeZoneByID(*id);
662                 delete id;
663
664                 TimeZoneTransition tzTrans;
665                 if (vtz->useDaylightTime() == TRUE) {
666                         if (trans == NEXT_TRANSITION)
667                                 result = vtz->getNextTransition(dstTransitionDate, FALSE,  tzTrans);
668                         else
669                                 result = vtz->getPreviousTransition(dstTransitionDate, FALSE,  tzTrans);
670                         if (result == TRUE) {
671                                 LogDebug("result is TRUE");
672                                 dstTransitionDate = tzTrans.getTime();
673                         }
674                 }
675                 delete vtz;
676
677                 if (result == false)
678                         return props;
679
680                 Calendar *dstTransCalendar = myCalendar->clone();
681                 dstTransCalendar->setTime(dstTransitionDate, ec);
682                 if (U_SUCCESS(ec)) {
683                         props =  _makeProperties(dstTransCalendar);
684                         delete dstTransCalendar;
685                         return props;
686                 }
687                 delete dstTransCalendar;
688         }
689         ThrowMsg(Commons::PlatformException, "can't getDSTTransition value from ICU");
690         return props;
691 }
692
693 }
694 }
695 }