tizen 2.3.1 release
[framework/web/wearable/wrt-plugins-tizen.git] / src / TimeUtil / TimeUtilTools.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        TimeUtilTools.cpp
20 */
21
22 #include <unicode/ustring.h>
23 #include <unicode/udat.h>
24 #include <unicode/dtptngen.h>
25 #include <string.h>
26 #include <vconf.h>
27 #include <memory>
28 #include <unistd.h>
29 #include <Commons/Exception.h>
30 #include <Logger.h>
31 #include "TimeUtilTools.h"
32 #include "JSUtil.h"
33
34 using namespace DeviceAPI::Common;
35
36 #ifdef IMPL_BACKWARD_COMPATIBLE
37 using namespace WrtDeviceApis;
38 #endif // IMPL_BACKWARD_COMPATIBLE
39
40 namespace DeviceAPI {
41 namespace Time {
42
43 std::string TimeUtilTools::toUTF8String(UnicodeString uniStr)
44 {
45     LOGD("Entered");
46
47     int bufferLen = sizeof(UChar) * static_cast<int>(uniStr.length()) + 1;
48     char *resultBuffer = static_cast<char*>(malloc(bufferLen));
49     if (!resultBuffer) {
50         LOGE("memory allocation error");
51         throw Common::UnknownException("memory allocation error");
52     }
53     memset(resultBuffer, 0, bufferLen);
54     CheckedArrayByteSink sink(resultBuffer, bufferLen);
55     uniStr.toUTF8(sink);
56     if (sink.Overflowed()) {
57         LOGE("Converting error");
58         free(resultBuffer);
59         throw Common::UnknownException("Converting error");
60     }
61
62     std::string str(resultBuffer);
63     free(resultBuffer);
64
65     return str;
66 }
67
68 UnicodeString *TimeUtilTools::toUnicodeString(const std::string& str)
69 {
70     LOGD("Entered");
71
72     UnicodeString *id = new UnicodeString(str.c_str());
73
74     return id;
75 }
76
77 int32_t TimeUtilTools::toint32_t(const long num)
78 {
79     LOGD("Entered");
80
81     return static_cast<int32_t>(num);
82 }
83
84 long TimeUtilTools::tolong(const int32_t num)
85 {
86     LOGD("Entered");
87
88     return static_cast<long>(num);
89 }
90
91 long long TimeUtilTools::tolonglong(const int32_t num)
92 {
93     LOGD("Entered");
94
95     return static_cast<long long>(num);
96 }
97
98 const std::vector<std::string>& TimeUtilTools::getTimezonesArray()
99 {
100     LOGD("Entered");
101
102     static bool initialized = false;
103     static std::vector <std::string> availableTimezones;
104     if (!initialized) {
105         initialized = true;
106         UErrorCode ec = U_ZERO_ERROR;
107         std::shared_ptr <StringEnumeration> tzen (TimeZone::createEnumeration());
108         const char *str = NULL;
109         int32_t count = tzen->count(ec);
110
111         if (U_SUCCESS(ec)) {
112             int i = 0;
113             do {
114                 int32_t resultLen = 0;
115                 str = tzen->next(&resultLen, ec);
116                 if (U_SUCCESS(ec) && str != NULL) {
117                     std::string timezone = str;
118                     availableTimezones.push_back(timezone);
119                     i++;
120                 }
121                 else {
122                     LOGE("An error occured: %d, %s", ec, u_errorName(ec));
123                     throw Common::UnknownException("An error occured");
124                 }
125             } while ((str != NULL) && (i < count));
126         }
127         else {
128             LOGE("Can't get timezones list: %d, %s", ec, u_errorName(ec));
129             throw Common::UnknownException("Can't get timezones list");
130         }
131     }
132     return availableTimezones;
133 }
134
135 std::string TimeUtilTools::getLocalTimeZone()
136 {
137     LOGD("Entered");
138
139     UnicodeString id;
140     std::shared_ptr <TimeZone> zone (TimeZone::createDefault());
141     zone->getID(id);
142
143     std::string s_result = TimeUtilTools::toUTF8String(id);
144
145     return s_result;
146 }
147
148 std::string TimeUtilTools::getDefaultTimezone()
149 {
150     LOGD("Entered");
151
152     enum { BUFFERSIZE = 1024 };
153     char buf[BUFFERSIZE];
154     std::string result;
155     ssize_t len = readlink("/opt/etc/localtime", buf, sizeof(buf)-1);
156     if (len != -1) {
157         buf[len] = '\0';
158     }
159     else {
160         /* handle error condition */
161         return result;
162     }
163     result = std::string(buf+20);
164
165     LOGD("tzpath = %s", result.c_str());
166     return result;
167 }
168
169 bool TimeUtilTools::isLeapyear(long year)
170 {
171     LOGD("Entered");
172
173     if ((year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))) {
174         return true;
175     }
176     return false;
177 }
178
179 bool TimeUtilTools::isInTimezonesArray(const std::string& timezone)
180 {
181     LOGD("Entered");
182
183     UnicodeString *id = TimeUtilTools::toUnicodeString(timezone);
184     TimeZone *tz = TimeZone::createTimeZone(*id);
185
186     UnicodeString timezone_id;
187     tz->getID(timezone_id);
188
189     bool result = false;
190     if (TimeUtilTools::toUTF8String(timezone_id) != "Etc/Unknown")
191         result = true;
192
193     delete tz;
194     tz = NULL;
195
196     delete id;
197     id = NULL;
198
199     return result;
200 }
201
202 long long TimeUtilTools::getMilliseconds(JSContextRef ctx, JSValueRef value)
203 {
204     LOGD("Entered");
205
206     JSObjectRef timeobj = NULL;
207     timeobj = JSUtil::JSValueToObject(ctx, value);
208     JSValueRef exception = NULL;
209     JSObjectRef getTime = NULL;
210     try {
211         getTime = JSUtil::JSValueToObject(ctx, JSUtil::getProperty(ctx, timeobj,
212                 "getTime"));
213     } catch (const TypeMismatchException& err) {
214         throw TypeMismatchException("Value is not Date Object");
215     }
216
217     JSValueRef timevalue = JSObjectCallAsFunction(ctx, getTime, timeobj, 0,
218             NULL, &exception);
219     if (exception != NULL)
220         throw TypeMismatchException("Value is not Date Object");
221
222     long long millisecond = JSUtil::JSValueToLongLong(ctx, timevalue);
223     return millisecond;
224 }
225
226 Locale *TimeUtilTools::getDefaultLocale()
227 {
228     LOGD("Entered");
229
230     char *tempstr = vconf_get_str(VCONFKEY_REGIONFORMAT);
231     if (NULL == tempstr) {
232         return NULL;
233     }
234
235     Locale *defaultLocale = NULL;
236
237     char *str_region = NULL;
238     char* p = strchr(tempstr, '.');
239     int len = strlen(tempstr) - strlen(".UTF-8");
240     if (p && len > 0) {
241         str_region = strndup(tempstr, len); //.UTF8 => 5
242         defaultLocale = new Locale(str_region);
243     }
244
245     free(tempstr);
246     free(str_region);
247
248     if (defaultLocale) {
249         if (defaultLocale->isBogus()) {
250             delete defaultLocale;
251             defaultLocale = NULL;
252         }
253     }
254
255     return defaultLocale;
256 }
257
258 UnicodeString TimeUtilTools::getDateTimeFormat(DateTimeFormatType type, bool bLocale)
259 {
260     LOGD("Entered");
261
262     UErrorCode ec = U_ZERO_ERROR;
263     Locale *defaultLocale = getDefaultLocale();
264
265     DateTimePatternGenerator *dateTimepattern =
266         DateTimePatternGenerator::createInstance(
267         ((bLocale && defaultLocale) ? *defaultLocale : Locale::getEnglish())
268         , ec);
269
270     delete defaultLocale;
271     if (U_SUCCESS(ec)) {
272
273         UnicodeString patten;
274
275         if (DATE_FORMAT == type) {
276             patten = dateTimepattern->getBestPattern(UDAT_YEAR_MONTH_WEEKDAY_DAY, ec);
277         } else if (DATE_SHORT_FORMAT == type) {
278             patten = dateTimepattern->getBestPattern(UDAT_YEAR_NUM_MONTH_DAY, ec);
279         }
280         else {
281             int ret = 0;
282             int value = 0;
283             ret = vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &value);
284             // if failed, set default time format
285             if (-1 == ret) {
286                 value = VCONFKEY_TIME_FORMAT_12;
287             }
288
289             std::string skeletone;
290             if (TIME_FORMAT != type) {
291                 skeletone = UDAT_YEAR_MONTH_WEEKDAY_DAY;
292             }
293             if (VCONFKEY_TIME_FORMAT_12 == value) {
294                 skeletone += "hhmmss";
295             } else {
296                 skeletone += "HHmmss";
297             }
298
299             UnicodeString *skeletoneUniStr = toUnicodeString(skeletone);
300             patten = dateTimepattern->getBestPattern(*skeletoneUniStr, ec);
301             delete skeletoneUniStr;
302
303             if (!bLocale)
304                 patten += " 'GMT'Z v'";
305         }
306
307     delete dateTimepattern;
308     return patten;
309
310     } else {
311         LOGE("Failed to create DateTimepattern: %d, %s", ec, u_errorName(ec));
312     }
313
314     delete dateTimepattern;
315     return "";
316 }
317
318 std::string TimeUtilTools::getDateFormat(bool shortformat)
319 {
320     LOGD("Entered");
321
322     UnicodeString timeFormat =
323         TimeUtilTools::getDateTimeFormat(
324             (shortformat ?
325                     TimeUtilTools::DATE_SHORT_FORMAT :
326                     TimeUtilTools::DATE_FORMAT),
327             true);
328     timeFormat = timeFormat.findAndReplace("E", "D");
329
330     if (timeFormat.indexOf("MMM") > 0) {
331         if (timeFormat.indexOf("MMMM") > 0) {
332             timeFormat = timeFormat.findAndReplace("MMMM", "M");
333         } else {
334             timeFormat = timeFormat.findAndReplace("MMM", "M");
335         }
336     } else {
337         timeFormat = timeFormat.findAndReplace("M", "m");
338     }
339
340     int32_t i = 0;
341
342     while (i < timeFormat.length()-1) {
343         if (timeFormat[i] == timeFormat[i+1])
344             timeFormat.remove(i, 1);
345         else
346             i++;
347     }
348
349     return TimeUtilTools::toUTF8String(timeFormat);
350 }
351
352 std::string TimeUtilTools::getTimeFormat()
353 {
354     LOGD("Entered");
355
356     UnicodeString timeFormat = TimeUtilTools::getDateTimeFormat(
357             TimeUtilTools::TIME_FORMAT, true);
358     timeFormat = timeFormat.findAndReplace("H", "h");
359     timeFormat = timeFormat.findAndReplace("K", "h");
360     timeFormat = timeFormat.findAndReplace("k", "h");
361     timeFormat = timeFormat.findAndReplace("a", "ap");
362
363     int32_t i = 0;
364
365     while (i < timeFormat.length()-1) {
366         if (timeFormat[i] == timeFormat[i+1]) {
367             timeFormat.remove(i, 1);
368         } else {
369             i++;
370         }
371     }
372     return TimeUtilTools::toUTF8String(timeFormat);
373 }
374
375 bool TimeUtilTools::compareTimeZoneName(const std::string& tz1, const std::string& tz2)
376 {
377     LOGD("Entered");
378
379     if (tz1 != tz2) {
380         return false;
381     }
382     return true;
383 }
384
385 #ifdef IMPL_BACKWARD_COMPATIBLE
386
387 int32_t TimeUtilTools::toint32_t(const long long num)
388 {
389     LOGD("Entered");
390
391     return static_cast<int32_t>(num);
392 }
393
394 int32_t TimeUtilTools::toint32_t(const int num)
395 {
396     LOGD("Entered");
397
398     return static_cast<int32_t>(num);
399 }
400
401 std::string TimeUtilTools::toString(UnicodeString uniStr)
402 {
403     LOGD("Entered");
404
405     int bufferLen = sizeof(UChar)*static_cast<int>(uniStr.length()) + 1;
406     char *resultBuffer = (char *)malloc(bufferLen);
407     if (!resultBuffer) {
408         ThrowMsg(Commons::PlatformException, "memory allocation error");
409     }
410
411     memset(resultBuffer, 0, bufferLen);
412     CheckedArrayByteSink sink(resultBuffer, bufferLen);
413     uniStr.toUTF8(sink);
414     if (sink.Overflowed()) {
415         ThrowMsg(Commons::PlatformException, "Converting error");
416     }
417
418     std::string str(resultBuffer);
419     free(resultBuffer);
420     LOGD("%s", str.c_str());
421     return str;
422 }
423
424 TimeZone *TimeUtilTools::makeTimeZone(const std::string &name)
425 {
426     LOGD("Entered,  timezone name : %s", name.c_str());
427
428     UnicodeString *id = toUnicodeString(name);
429
430     TimeZone *tz = TimeZone::createTimeZone(*id);
431     delete id;
432
433     return tz;
434 }
435
436 void TimeUtilTools::printDate(Calendar *cal)
437 {
438     LOGD("Entered");
439
440     if (cal == NULL) {
441         return;
442     }
443
444     UErrorCode ec = U_ZERO_ERROR;
445
446     LOGI("year : %ld", tolong(cal->get(UCAL_YEAR, ec)));
447     LOGI("month : %ld", tolong(cal->get(UCAL_MONTH, ec)));
448     LOGI("day : %ld", tolong(cal->get(UCAL_DATE, ec)));
449     LOGI("hours : %ld", tolong(cal->get(UCAL_HOUR, ec)));
450     LOGI("hours of day : %ld", tolong(cal->get(UCAL_HOUR_OF_DAY, ec)));
451     LOGI("AM/PM : %ld", tolong(cal->get(UCAL_AM_PM, ec)));
452     LOGI("dayofweek : %ld", tolong(cal->get(UCAL_DAY_OF_WEEK, ec)));
453     LOGI("minues : %ld", tolong(cal->get(UCAL_MINUTE, ec)));
454     LOGI("seconds : %ld", tolong(cal->get(UCAL_SECOND, ec)));
455     LOGI("miliseconds : %ld", tolong(cal->get(UCAL_MILLISECOND, ec)));
456     LOGI("zone offset : %ld", tolong(cal->get(UCAL_ZONE_OFFSET, ec)));
457     LOGI("dst offset : %ld", tolong(cal->get(UCAL_DST_OFFSET, ec)));
458     LOGI("is leap month? : %ld", tolong(cal->get(UCAL_IS_LEAP_MONTH, ec)));
459 }
460
461 #endif // IMPL_BACKWARD_COMPATIBLE
462
463 } // Time
464 } // DeviceAPI