upload tizen1.0 source
[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 <vconf.h>
23
24 #include <Commons/Exception.h>
25
26 #include <unicode/timezone.h>
27 #include <unicode/vtzone.h>
28 #include <unicode/smpdtfmt.h>
29
30 #include "TZDate.h"
31 #include "TimeUtilTools.h"
32
33 using namespace TizenApis::Api::TimeUtil;
34 using namespace WrtDeviceApis;
35
36 namespace TizenApis {
37 namespace Platform {
38 namespace TimeUtil {
39         
40 TZDate::TZDate(const bool isNotNull)
41 {
42         LogDebug("entered");
43         
44         if (isNotNull == FALSE) {
45                 myCalendar = NULL;
46         } else {
47                 UErrorCode ec = U_ZERO_ERROR;
48                 myCalendar = Calendar::createInstance(ec);
49
50                 if (U_SUCCESS(ec)) {
51                         TimeUtilTools Util;
52                         Util.printDate(myCalendar);
53                 }
54                 else {
55                         myCalendar = NULL;
56                         ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
57                 }
58         }
59 }
60
61 TZDate::TZDate(const std::string &timezone)
62 {
63         LogDebug("entered");
64         
65         UErrorCode ec = U_ZERO_ERROR;
66         TimeUtilTools Util;     
67         myCalendar = Calendar::createInstance(Util.makeTimeZone(timezone) ,ec);
68
69         if (U_SUCCESS(ec)) {
70                 TimeUtilTools Util;
71                 Util.printDate(myCalendar);
72         }
73         else {
74                 myCalendar = NULL;
75                 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
76         }
77
78 }
79
80 TZDate::TZDate(const TZDateProperties &properties)
81 {
82         LogDebug("entered");
83
84         UErrorCode ec = U_ZERO_ERROR;
85         TimeUtilTools Util;     
86         if (properties.timezone == "") {
87                 myCalendar = Calendar::createInstance(ec);
88                 if (U_SUCCESS(ec)) {    
89                         myCalendar->set(Util.toint32_t(properties.year), Util.toint32_t(properties.month), 
90                         Util.toint32_t(properties.day), Util.toint32_t(properties.hours), Util.toint32_t(properties.minutes), Util.toint32_t(properties.seconds));
91                         set(TZDATE_MILLISECOND, properties.milliseconds);
92                 } else {
93                         myCalendar = NULL;
94                 }
95         } else {
96                 myCalendar = _makeCalendar(properties);
97         }
98
99         if (myCalendar != NULL) {       
100                 Util.printDate(myCalendar);
101         }
102         else {
103                 ThrowMsg(Commons::PlatformException, "Can't make to ICU Calendar");
104         }
105 }
106
107 TZDate::~TZDate()
108 {
109         LogDebug("entered");
110
111         if (myCalendar != NULL)
112                 delete myCalendar;
113
114         myCalendar = NULL;
115
116 }
117
118 bool  TZDate::isNull()
119 {
120         if (myCalendar == NULL)
121                 return TRUE;
122         
123         return FALSE;
124 }
125
126 Calendar *TZDate::_makeCalendar(const TZDateProperties &properties)
127 {
128         LogDebug("entered");
129         UErrorCode ec = U_ZERO_ERROR;
130         TimeUtilTools Util;     
131
132         Calendar *cal = Calendar::createInstance(Util.makeTimeZone(properties.timezone) ,ec);
133         if (U_SUCCESS(ec)) {
134                 cal->set(Util.toint32_t(properties.year), Util.toint32_t(properties.month), 
135                         Util.toint32_t(properties.day), Util.toint32_t(properties.hours), Util.toint32_t(properties.minutes), Util.toint32_t(properties.seconds));
136                 cal->set(UCAL_MILLISECOND, Util.toint32_t(properties.milliseconds));
137                 return cal;
138         }
139
140         return NULL;
141 }
142
143 std::string TZDate::_getTimezoneName(Calendar *cal)
144 {
145         UnicodeString ID;
146         TimeUtilTools Util;
147         
148         cal->getTimeZone().getID(ID);
149         std::string s_result = Util.toString(ID);
150         LogDebug(s_result);
151         return s_result;        
152 }
153
154 const UCalendarDateFields TZDate::_convertDateField(const TZDateFields field)
155 {
156         switch (field) {
157         case TZDATE_ERA:
158                 return UCAL_ERA;
159                 break;
160         case TZDATE_YEAR:
161                 return UCAL_YEAR;
162                 break;
163         case TZDATE_MONTH:
164                 return UCAL_MONTH;
165                 break;
166         case TZDATE_WEEK_OF_YEAR:
167                 return UCAL_WEEK_OF_YEAR;
168                 break;
169         case TZDATE_WEEK_OF_MONTH:
170                 return UCAL_WEEK_OF_MONTH;
171                 break;
172         case TZDATE_DATE:
173                 return UCAL_DATE;
174                 break;
175         case TZDATE_DAY_OF_YEAR:
176                 return UCAL_DAY_OF_YEAR;
177                 break;
178         case TZDATE_DAY_OF_WEEK:
179                 return UCAL_DAY_OF_WEEK;
180                 break;
181         case TZDATE_DAY_OF_WEEK_IN_MONTH:
182                 return UCAL_DAY_OF_WEEK_IN_MONTH;
183                 break;          
184         case TZDATE_AM_PM:
185                 return UCAL_AM_PM;
186                 break;
187         case TZDATE_HOUR:
188                 return UCAL_HOUR;
189                 break;          
190         case TZDATE_HOUR_OF_DAY:
191                 return UCAL_HOUR_OF_DAY;
192                 break;
193         case TZDATE_MINUTE:
194                 return UCAL_MINUTE;
195                 break;
196         case TZDATE_SECOND:
197                 return UCAL_SECOND;
198                 break;
199         case TZDATE_MILLISECOND:
200                 return UCAL_MILLISECOND;
201                 break;          
202         case TZDATE_ZONE_OFFSET:
203                 return UCAL_ZONE_OFFSET;
204                 break;
205         case TZDATE_DST_OFFSET:
206                 return UCAL_DST_OFFSET;
207                 break;
208         default:
209                 return UCAL_FIELD_COUNT;
210         }
211 }
212
213 TZDateProperties TZDate::_makeProperties(Calendar *cal)
214 {
215         TZDateProperties result;
216         TimeUtilTools Util;
217         
218         result.year = _get(TZDATE_YEAR, cal);
219         result.month = _get(TZDATE_MONTH,cal);
220         result.day = _get(TZDATE_DATE, cal);
221         result.hours = _get(TZDATE_HOUR_OF_DAY, cal);
222         result.minutes = _get(TZDATE_MINUTE, cal);
223         result.seconds = _get(TZDATE_SECOND, cal);
224         result.milliseconds = _get(TZDATE_MILLISECOND, cal);
225         result.timezone=  _getTimezoneName(cal);
226
227         return result;
228 }
229
230 std::string TZDate::getTimezone()
231 {
232         return _getTimezoneName(myCalendar);
233 }
234
235 TZDateProperties TZDate::toTimezone(const std::string timezone) {
236         TimeUtilTools Util;
237         Calendar *newCalendar = myCalendar->clone();
238         newCalendar->setTimeZone(*(Util.makeTimeZone(timezone)));
239         
240         TZDateProperties newProps =  _makeProperties(newCalendar);
241         delete newCalendar;
242         if ((newProps.timezone != timezone) && (newProps.timezone == "Etc/Unknown"))
243                 ThrowMsg(Commons::InvalidArgumentException, "Unsupported Timezone.");
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         UDate myTime = myCalendar->getTime(ec);
342
343         if (U_SUCCESS(ec)) {
344                 UDate otherTime = otherCalendar->getTime(ec);
345                 if (U_SUCCESS(ec)) {
346                         LogDebug("myCalendar");
347                         Util.printDate(myCalendar);
348                         LogDebug("otherCalendar");
349                         Util.printDate(otherCalendar);
350                         delete otherCalendar;
351                         
352                         LogDebug("myTime : " <<myTime);
353                         LogDebug("otherTime : " << otherTime);
354                         
355                         return static_cast<long long>(myTime - otherTime);
356                 }
357         }
358         delete otherCalendar;
359         ThrowMsg(Commons::PlatformException, "Calendar error in difference");
360         return 0;
361 }
362
363 TZDateProperties TZDate::addDuration(const DurationProperties &duration) {
364         LogDebug("entered");
365         UErrorCode ec = U_ZERO_ERROR;
366         
367         TimeUtilTools Util;
368
369         Calendar *cal = myCalendar->clone();
370         if (duration.unit == DAYS_UNIT) {
371                 cal->add(UCAL_DATE, Util.toint32_t(duration.length), ec);
372         } else if (duration.unit == MINUTES_UNIT) {
373                 cal->add(UCAL_MINUTE, Util.toint32_t(duration.length), ec);
374         } else if (duration.unit == HOURS_UNIT) {
375                 cal->add(UCAL_HOUR_OF_DAY, Util.toint32_t(duration.length), ec);
376         } else if (duration.unit == MSECS_UNIT) {
377                 cal->add(UCAL_MILLISECOND, Util.toint32_t(duration.length), ec);
378         } else {
379                 cal->add(UCAL_SECOND, Util.toint32_t(duration.length), ec);
380         }
381         TZDateProperties result = _makeProperties(cal);
382         Util.printDate(cal);
383         delete cal;
384
385         if (!U_SUCCESS(ec))
386                 ThrowMsg(Commons::PlatformException, "Calendar error in addDuration");
387         return result;
388         
389 }
390
391 TZDateProperties TZDate::toUTC() {
392         LogDebug("entered");
393         TimeUtilTools Util;
394         TZDateProperties result;
395         Calendar *UTCCalendar = myCalendar->clone();
396
397         try {
398                 UTCCalendar->setTimeZone(*(TimeZone::getGMT()));
399                 result = _makeProperties(UTCCalendar);
400                 Util.printDate(UTCCalendar);
401                 delete UTCCalendar;
402         } catch (Commons::PlatformException) {
403                 delete UTCCalendar;
404                 ThrowMsg(Commons::PlatformException, "Calendar error in toUTC");
405         }
406
407         return result;
408 }
409
410 TZDateProperties TZDate::toLocalTimezone() {
411         LogDebug("entered");
412         TimeUtilTools Util;
413         TZDateProperties result;
414         Calendar *localCalendar = myCalendar->clone();
415         
416         try {
417                 localCalendar->setTimeZone(*(TimeZone::createDefault()));
418                 result = _makeProperties(localCalendar);
419                 Util.printDate(localCalendar);
420                 delete localCalendar;
421         } catch (Commons::PlatformException) {
422                 delete localCalendar;
423                 ThrowMsg(Commons::PlatformException, "Calendar error in toLocalTimezone");
424         }
425         return result;  
426 }
427
428 double TZDate::getTime() {
429         LogDebug("entered");
430         UErrorCode ec = U_ZERO_ERROR;
431
432         UDate date = myCalendar->getTime(ec);
433         if (U_SUCCESS(ec))
434                 return static_cast<double>(date);
435
436         ThrowMsg(Commons::PlatformException, "can't get time");
437         return 0;
438 }
439
440  std::string TZDate::toDateString(bool bLocale)  {
441         UErrorCode ec = U_ZERO_ERROR;
442         UnicodeString str;
443         TimeUtilTools Util;
444         
445         DateFormat *fmt = new SimpleDateFormat(Util.getDateTimeFormat(TimeUtilTools::DATE_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
446         if (U_SUCCESS(ec)) {
447                 fmt->setCalendar(*myCalendar);
448                 fmt->format(myCalendar->getTime(ec), str);
449                 delete fmt;
450
451                 if (U_SUCCESS(ec)) {
452                         std::string result = Util.toString(str);
453                         str.remove();
454                         
455                         LogDebug (result);
456                         return result;
457                 }
458         }
459
460         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
461         return "";
462  }
463
464   std::string TZDate::toTimeString(bool bLocale)  {
465
466         UErrorCode ec = U_ZERO_ERROR;
467         UnicodeString str;
468         TimeUtilTools Util;
469         
470         DateFormat *fmt = new SimpleDateFormat(Util.getDateTimeFormat(TimeUtilTools::TIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
471         if (U_SUCCESS(ec)) {
472                 fmt->setCalendar(*myCalendar);
473                 fmt->format(myCalendar->getTime(ec), str);
474                 delete fmt;
475
476                 if (U_SUCCESS(ec)) {
477                         std::string result = Util.toString(str);
478                         str.remove();
479                         LogDebug (result);
480                         return result;
481                 }
482         }
483         
484         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
485         return "";
486  }
487  
488  std::string TZDate::toString(bool bLocale) {
489         LogDebug("entered");
490
491         UErrorCode ec = U_ZERO_ERROR;
492         UnicodeString str;
493         TimeUtilTools Util;
494         
495         DateFormat *fmt = new SimpleDateFormat(Util.getDateTimeFormat(TimeUtilTools::DATETIME_FORMAT, bLocale), (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec);
496         if (U_SUCCESS(ec)) {
497                 fmt->setCalendar(*myCalendar);
498                 fmt->format(myCalendar->getTime(ec), str);
499                 delete fmt;
500
501                 if (U_SUCCESS(ec)) {
502                         std::string result = Util.toString(str);
503                         str.remove();
504                         LogDebug (result);
505                         return result;
506                 }
507         }
508         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
509         return "";
510 }
511
512 std::string TZDate::getTimezoneAbbreviation() {
513         LogDebug("entered");
514
515         UErrorCode ec = U_ZERO_ERROR;
516         UnicodeString str;
517         TimeUtilTools Util;
518         
519         DateFormat *fmt = new SimpleDateFormat(UnicodeString("V"), Locale::getEnglish(), ec);
520         if (U_SUCCESS(ec)) {
521                 fmt->setCalendar(*myCalendar);
522                 fmt->format(myCalendar->getTime(ec), str);
523                 delete fmt;
524
525                 if (U_SUCCESS(ec)) {
526                         std::string result = Util.toString(str);
527                         str.remove();
528
529                         LogDebug (result);
530
531                         return result;
532                 }
533         }
534         ThrowMsg(Commons::PlatformException, "can't make SimpleDateFormat or can't get time");
535         return "";
536 }
537
538 long TZDate::secondsFromUTC() {
539         LogDebug("entered");
540         UErrorCode ec = U_ZERO_ERROR;
541         TimeUtilTools Util;
542
543         int32_t zoneOffset = myCalendar->get(UCAL_ZONE_OFFSET, ec);
544         if (!U_SUCCESS(ec)) {
545                 ThrowMsg(Commons::PlatformException, "can't get zone offset");
546                 return 0;
547         }
548         
549         int32_t dstOffset = myCalendar->get(UCAL_DST_OFFSET, ec);
550         if (!U_SUCCESS(ec)) {
551                 ThrowMsg(Commons::PlatformException, "can't get dst offset");
552                 return 0;
553         }
554         
555         long result = ( Util.tolong(zoneOffset + dstOffset)) / MILLISTOSEC;
556
557         LogDebug("result : " << result);
558         return result;
559 }
560
561 bool TZDate::isDST() {
562         LogDebug("entered");
563         UErrorCode ec = U_ZERO_ERROR;
564         TimeUtilTools Util;
565         UBool result = myCalendar->inDaylightTime(ec);
566
567         if (!U_SUCCESS(ec)) {
568                 ThrowMsg(Commons::PlatformException, "can't inDaylightTime value from ICU");
569                 return FALSE;
570         }
571
572         return static_cast<bool>(result);
573 }
574
575 TZDateProperties TZDate::getDSTTransition(DSTTransition trans) {
576         LogDebug("entered");
577         TimeUtilTools Util;
578         UErrorCode ec = U_ZERO_ERROR;
579         TZDateProperties props;
580         UDate DSTTransitionDate = myCalendar->getTime(ec);
581         UBool result = false;
582
583         if (U_SUCCESS(ec)) {
584                 UnicodeString *ID = Util.toUnicodeString(getTimezone());
585
586                 VTimeZone *Vtz = VTimeZone::createVTimeZoneByID(*ID);
587                 delete ID;
588
589                 TimeZoneTransition tzTrans;
590                 if (Vtz->useDaylightTime() == TRUE) {
591                         if (trans == NEXT_TRANSITION)
592                                 result = Vtz->getNextTransition(DSTTransitionDate, FALSE,  tzTrans);
593                         else
594                                 result = Vtz->getPreviousTransition(DSTTransitionDate, FALSE,  tzTrans);
595                         if (result == TRUE) {
596                                 LogDebug("result is TRUE");
597                                 DSTTransitionDate = tzTrans.getTime();          
598                         }
599                 }
600                 delete Vtz;
601
602                 if (result == false)
603                         return props;
604
605                 Calendar *DSTTransCalendar = myCalendar->clone();
606                 DSTTransCalendar->setTime(DSTTransitionDate, ec);
607                 if (U_SUCCESS(ec)) {
608                         props =  _makeProperties(DSTTransCalendar);
609                         delete DSTTransCalendar;
610                         return props;
611                 }
612                 delete DSTTransCalendar;
613         }
614         ThrowMsg(Commons::PlatformException, "can't getDSTTransition value from ICU");
615         return props;
616 }
617
618 }
619 }
620 }