Update change log and spec for wrt-plugins-tizen_0.4.57
[platform/framework/web/wrt-plugins-tizen.git] / src / TimeUtil / TimeUtilConverter.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 #include <Commons/Exception.h>
19 #include <CommonsJavaScript/ScopedJSStringRef.h>
20 #include <CommonsJavaScript/PrivateObject.h>
21 #include <CommonsJavaScript/Validator.h>
22 #include <CommonsJavaScript/JSUtils.h>
23 #include <Commons/RegexUtils.h>
24
25 #include "TimeUtilConverter.h"
26 #include "JSTZDate.h"
27 #include "JSTimeDuration.h"
28 #include <Logger.h>
29
30 using namespace WrtDeviceApis;
31
32 namespace DeviceAPI {
33 namespace Time {
34
35 TimeUtilConverter::TimeUtilConverter(JSContextRef context)
36 : WrtDeviceApis::CommonsJavaScript::Converter(context) {
37 }
38
39 TimeUtilConverter::~TimeUtilConverter() {
40 }
41
42 short TimeUtilConverter::toShort(const JSValueRef& arg)
43 {
44     double tmp = toNumber_(arg);
45     return (isNan(tmp) ? 0 : static_cast<short>(tmp));
46 }
47
48 TZDateProperties TimeUtilConverter::getPropertiesInTZDate(JSValueRef arg) {
49         if (JSValueIsNull(m_context, arg) || JSValueIsUndefined(m_context, arg) || !JSValueIsObjectOfClass(m_context, arg, JSTZDate::getClassRef())) {
50                 ThrowMsg(Commons::ConversionException,
51                          "Wrong Input Type");
52         }
53         JSObjectRef obj = toJSObjectRef(arg);
54         return getPropertiesInTZDate(obj);
55 }
56
57
58 TZDateProperties TimeUtilConverter::getPropertiesInTZDate(JSObjectRef arg) {
59         LoggerD("TZDate object=" << arg);
60         if (!arg) {
61                 LoggerE("Object is null");
62                 ThrowMsg(Commons::ConversionException, "Private object not initialized");
63         }
64         TZDatePrivObject* privateObject = static_cast<TZDatePrivObject*>(JSObjectGetPrivate(arg));
65         if (!privateObject) {
66                 LoggerE("Private object is not set.");
67                 ThrowMsg(Commons::ConversionException, "Private object not initialized");
68         }
69         
70         TZDatePtr tzDate = privateObject->getObject();
71         TZDateProperties result;
72
73         result.timezone = tzDate->getTimezone();
74         result.year = tzDate->get(TZDate::TZDATE_YEAR);
75         result.month = tzDate->get(TZDate::TZDATE_MONTH);
76         result.day= tzDate->get(TZDate::TZDATE_DATE);
77         result.hours= tzDate->get(TZDate::TZDATE_HOUR_OF_DAY);
78         result.minutes= tzDate->get(TZDate::TZDATE_MINUTE);
79         result.seconds= tzDate->get(TZDate::TZDATE_SECOND);
80         result.milliseconds = tzDate->get(TZDate::TZDATE_MILLISECOND);
81         return result;
82 }
83
84 JSObjectRef TimeUtilConverter::makeDurationObject(const DurationProperties &duration) {
85         return JSTimeDuration::createJSObject(m_context, duration);
86 }
87
88 JSObjectRef TimeUtilConverter::makeMillisecondDurationObject(const long long length) {
89         DurationProperties duration;
90         duration.length = length;
91         duration.unit = MSECS_UNIT;
92         const long long dayToMsecs = 1000 * 60 * 60 * 24;
93         if ((length % dayToMsecs) == 0) {
94                 duration.length = length / dayToMsecs;
95                 duration.unit = DAYS_UNIT;
96         }
97
98         return makeDurationObject(duration);
99 }
100
101 DurationPropertiesPtr TimeUtilConverter::getDuration(JSValueRef value) {
102         if (!JSValueIsObjectOfClass(m_context, value, JSTimeDuration::getClassRef())) {
103                 ThrowMsg(Commons::ConversionException, "Wrong input type");
104         }
105
106         TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(toJSObjectRef(value)));
107         DurationPropertiesPtr duration = privateObject->getObject();
108         return duration;
109 }
110
111 DurationProperties TimeUtilConverter::getDurationProperties(JSValueRef value) {
112         DurationProperties duration;
113         duration.length = getDurationLength(value);
114         duration.unit = getDurationUnit(value);
115         if (duration.unit == WRONG_UNIT)
116                 ThrowMsg(Commons::ConversionException, "Wrong Unit");
117         return duration;
118 }
119
120 long long TimeUtilConverter::getDurationLength(JSValueRef value) {
121         if (JSValueIsNull(m_context, value) || JSValueIsUndefined(m_context, value) || !JSValueIsObjectOfClass(m_context, value, JSTimeDuration::getClassRef())) {
122                 ThrowMsg(Commons::ConversionException,
123                          "Wrong input type");
124         }
125         JSObjectRef obj = toJSObjectRef(value);
126         return getDurationLength(obj);
127 }
128
129 long long TimeUtilConverter::getDurationLength(JSObjectRef object) {
130         TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
131         if (!privateObject) {
132                 LoggerE("Private object is not set.");
133                 ThrowMsg(Commons::ConversionException, "Private object not initialized");
134         }
135
136         DurationPropertiesPtr duration = privateObject->getObject();
137
138         return duration->length;
139 }
140
141 short TimeUtilConverter::getDurationUnit(JSValueRef value) {
142         if (JSValueIsNull(m_context, value) || JSValueIsUndefined(m_context, value) || !JSValueIsObjectOfClass(m_context, value, JSTimeDuration::getClassRef())) {
143                 ThrowMsg(Commons::ConversionException,
144                          "Wrong input type");
145         }
146         JSObjectRef obj = toJSObjectRef(value);
147         return getDurationUnit(obj);
148 }
149
150 short TimeUtilConverter::getDurationUnit(JSObjectRef object) {
151         TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
152         if (!privateObject) {
153                 LoggerE("Private object is not set.");
154                 ThrowMsg(Commons::ConversionException, "Private object not initialized");
155         }
156
157         DurationPropertiesPtr duration = privateObject->getObject();
158
159         return duration->unit;
160
161 }
162
163 std::string TimeUtilConverter::getDurationUnitString(JSValueRef value) {
164         if (JSValueIsNull(m_context, value) || JSValueIsUndefined(m_context, value) || !JSValueIsObjectOfClass(m_context, value, JSTimeDuration::getClassRef())) {
165                 ThrowMsg(Commons::ConversionException,
166                          "Wrong input type");
167         }
168         JSObjectRef obj = toJSObjectRef(value);
169         return getDurationUnitString(obj);
170 }
171
172 std::string TimeUtilConverter::getDurationUnitString(JSObjectRef object) {
173         TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
174         if (!privateObject) {
175                 LoggerE("Private object is not set.");
176                 ThrowMsg(Commons::ConversionException, "Private object not initialized");
177         }
178
179         DurationPropertiesPtr duration = privateObject->getObject();
180
181         return duration->unitStr;
182
183 }
184
185 short TimeUtilConverter::toDurationUnit(std::string strUnit) {
186         if (!strUnit.compare("DAYS"))
187                 return DAYS_UNIT;
188         else if (!strUnit.compare("SECS"))
189                 return SECONDS_UNIT;
190         else if (!strUnit.compare("MINS"))
191                 return MINUTES_UNIT;
192         else if (!strUnit.compare("HOURS"))
193                 return HOURS_UNIT;
194         else if (!strUnit.compare("MSECS"))
195                 return  MSECS_UNIT;
196         else
197                 return WRONG_UNIT;
198 }
199
200 std::string TimeUtilConverter::toDurationUnitString(short unit) {
201         switch (unit) {
202                 case DAYS_UNIT:
203                         return "DAYS";
204                 case SECONDS_UNIT:
205                         return "SECS";
206                 case MINUTES_UNIT:
207                         return "MINS";
208                 case HOURS_UNIT:
209                         return "HOURS";
210                 case MSECS_UNIT:
211                         return "MSECS";
212                 default:
213                         return "";
214         }
215 }
216
217 long long TimeUtilConverter::convertDurationLength(DurationProperties duration, short unit) {
218         if ((duration.unit == WRONG_UNIT) || (unit == WRONG_UNIT))
219                 ThrowMsg(Commons::ConversionException, "Wrong Unit");
220         if (duration.unit < unit)
221                 ThrowMsg(Commons::ConversionException, "Unit is larger than duration's unit");
222
223         if (duration.unit == unit)
224                 return duration.length;
225
226         long long result = duration.length;
227
228         switch(unit) {
229                 case MSECS_UNIT:
230                         result = result * 1000;
231                         if (duration.unit == SECONDS_UNIT)
232                                 return result;
233                         // intentional fall-through
234
235                 case SECONDS_UNIT:
236                         result = result * 60;
237                         if (duration.unit == MINUTES_UNIT)
238                                 return result;
239                         // intentional fall-through
240
241                 case MINUTES_UNIT:
242                         result = result * 60;
243                         if (duration.unit == HOURS_UNIT)
244                                 return result;
245                         // intentional fall-through
246
247                 case HOURS_UNIT:
248                         result = result * 24;
249                         return result;
250                         // intentional fall-through
251         }
252     return result;
253 }
254
255 DurationProperties TimeUtilConverter::optimizedTimeDuration(DurationProperties origin) {
256         DurationProperties result;
257         result.unit = origin.unit;
258         result.length = origin.length;
259
260         switch(origin.unit) {
261                 case MSECS_UNIT:
262                         if (result.length % 1000)
263                                 return result;
264                         result.unit = SECONDS_UNIT;
265                         result.length /= 1000;
266                         // intentional fall-through
267
268                 case SECONDS_UNIT:
269                         if (result.length % 60)
270                                 return result;
271                         result.unit = MINUTES_UNIT;
272                         result.length /= 60;
273                         // intentional fall-through
274
275                 case MINUTES_UNIT:
276                         if (result.length % 60)
277                                 return result;
278                         result.unit = HOURS_UNIT;
279                         result.length /= 60;
280                         // intentional fall-through
281
282                 case HOURS_UNIT:
283                         if (result.length % 24)
284                                 return result;
285                         result.unit = DAYS_UNIT;
286                         result.length /= 24;
287                         // intentional fall-through
288         }       
289         result.unitStr = toDurationUnitString(result.unit);
290         return result;
291 }
292
293 double TimeUtilConverter::getTimeInMilliseconds(JSValueRef arg) {
294         if (JSValueIsNull(m_context, arg) || JSValueIsUndefined(m_context, arg) || !JSValueIsObjectOfClass(m_context, arg, JSTZDate::getClassRef())) {
295                 ThrowMsg(Commons::ConversionException,
296                          "Wrong input type");
297         }
298         JSObjectRef obj = toJSObjectRef(arg);
299
300         return getTimeInMilliseconds(obj);
301 }
302
303 double TimeUtilConverter::getTimeInMilliseconds(JSObjectRef arg) {
304         if (!arg) {
305                 LoggerE("Object is null");
306                 ThrowMsg(Commons::ConversionException, "Object is null");
307         }
308
309         TZDatePrivObject* privateObject = static_cast<TZDatePrivObject*>(JSObjectGetPrivate(arg));
310         if (!privateObject) {
311                 LoggerE("Private object is not set.");
312                 ThrowMsg(Commons::ConversionException, "Private object not initialized");
313         }
314
315         TZDatePtr tzDate = privateObject->getObject();
316
317         return tzDate->getTime();
318 }
319
320 tm TimeUtilConverter::toTZDateTime(JSValueRef arg) {
321         if (JSValueIsNull(m_context, arg) || JSValueIsUndefined(m_context, arg) || !JSValueIsObjectOfClass(m_context, arg, JSTZDate::getClassRef())) {
322                 ThrowMsg(Commons::ConversionException,
323                          "Wrong input type");
324         }
325         JSObjectRef obj = toJSObjectRef(arg);
326
327         return toTZDateTime(obj);
328 }
329
330 tm TimeUtilConverter::toTZDateTime(JSObjectRef arg) {
331         if (!arg) {
332                 LoggerE("Object is null");
333                 ThrowMsg(Commons::ConversionException, "Object is null");
334         }
335
336         TZDatePrivObject* privateObject = static_cast<TZDatePrivObject*>(JSObjectGetPrivate(arg));
337         if (!privateObject) {
338                 LoggerE("Private object is not set.");
339                 ThrowMsg(Commons::ConversionException, "Private object not initialized");
340         }
341
342         TZDatePtr tzDate = privateObject->getObject();
343         TZDatePtr utcTzDate(new TZDate(tzDate->getUTCTimezoneName()));
344         if (!utcTzDate->setTime(tzDate->getTime()))
345                 ThrowMsg(Commons::ConversionException, "Can not set Time");
346
347         TZDateProperties utcProperties = utcTzDate->makeProperties();
348         struct tm  utcTm;
349         memset(&utcTm, 0, sizeof(utcTm));
350
351         utcTm.tm_year = utcProperties.year - 1900;
352         utcTm.tm_mon = utcProperties.month;
353         utcTm.tm_mday= utcProperties.day;
354         utcTm.tm_hour= utcProperties.hours;
355         utcTm.tm_min=utcProperties.minutes;
356         utcTm.tm_sec= utcProperties.seconds;
357         utcTm.tm_isdst = 0;
358         return utcTm;
359 }
360
361 JSObjectRef TimeUtilConverter::toJSValueRefTZDate(const double milliseconds, const std::string &timezone) {
362         return JSTZDate::createJSObject(m_context, milliseconds, timezone);
363 }
364
365 }
366 }