From ca6e1db344014035751985fbcd3c998018f397b4 Mon Sep 17 00:00:00 2001 From: Andrzej Popowski Date: Fri, 24 Jul 2015 08:26:02 +0200 Subject: [PATCH] [Time] - fixing bugs with timezones [Verification] - TCT results 100% for Alarm, Calendar, Exif and Time Change-Id: Ifd9f74315c8374d5331ff44185cdbe8ea80fb054 Signed-off-by: Andrzej Popowski --- src/calendar/calendar_instance.cc | 4 +- src/time/time_api.js | 127 ++++++++++++++++++++---------- src/time/time_instance.cc | 75 ++++++++++-------- src/time/time_instance.h | 1 + src/utils/utils_api.js | 10 ++- 5 files changed, 138 insertions(+), 79 deletions(-) diff --git a/src/calendar/calendar_instance.cc b/src/calendar/calendar_instance.cc index 70d9a076..733c3548 100755 --- a/src/calendar/calendar_instance.cc +++ b/src/calendar/calendar_instance.cc @@ -96,9 +96,9 @@ void CalendarInstance::CalendarAdd(const JsonValue& args, JsonObject& out) { PlatformResult status = calendar_.Add(common::JsonCast(args), val.get()); - if (status.IsSuccess()) + if (status.IsSuccess()) { ReportSuccess(val, out); - else{ + } else{ LoggerE("Failed"); ReportError(status, &out); } diff --git a/src/time/time_api.js b/src/time/time_api.js index 0d4afaef..11a1fe41 100644 --- a/src/time/time_api.js +++ b/src/time/time_api.js @@ -281,50 +281,91 @@ tizen.TimeDuration.prototype.toString = function() { return this.length + ' ' + this.unit; }; +function getTimezoneOffset(_timezone, _timeInMs) { + var result = native_.callSync('Time_getTimeZoneOffset', { + timezone: _timezone, + value: _timeInMs + }); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + + return native_.getResultObject(result); +} + +function getMsUTC(date, timezone) { + var ms_utc = Date.UTC(date.getUTCFullYear(), + date.getUTCMonth(), + date.getUTCDate(), + date.getUTCHours(), + date.getUTCMinutes(), + date.getUTCSeconds(), + date.getUTCMilliseconds()); + if (arguments.length === 2) { + var result = native_.callSync('Time_getMsUTC', { + timezone: timezone, + value: ms_utc + }); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + + ms_utc = native_.getResultObject(result); + } + + return ms_utc; +} + tizen.TZDate = function(year, month, day, hours, minutes, seconds, milliseconds, timezone) { validator_.isConstructorCall(this, tizen.TZDate); - this.timezone_ = timezone || tizen.time.getLocalTimezone(); + if (timezone) { + if (tizen.time.getAvailableTimezones().indexOf(timezone) < 0) { + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR); + } + + this.timezone_ = timezone; + } else { + this.timezone_ = tizen.time.getLocalTimezone(); + } var hours = hours || 0; var minutes = minutes || 0; var seconds = seconds || 0; var milliseconds = milliseconds || 0; - if (!arguments.length) + if (!arguments.length) { this.date_ = new Date(); - else if (arguments.length === 1 || arguments.length === 2) { - if (arguments[0] instanceof Date) + } else if (arguments.length === 1 || arguments.length === 2) { + if (arguments[0] instanceof Date) { this.date_ = arguments[0]; - else + } else { this.date_ = new Date(); - if (arguments[1]) + } + if (arguments[1]) { + if (tizen.time.getAvailableTimezones().indexOf(arguments[1]) < 0) { + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR); + } this.timezone_ = arguments[1]; + } + } else { + this.date_ = {}; + if (timezone) { + var d = new Date(); + d.setUTCFullYear(year); + d.setUTCMonth(month); + d.setUTCDate(day); + d.setUTCHours(hours); + d.setUTCMinutes(minutes); + d.setUTCSeconds(seconds); + d.setUTCMilliseconds(milliseconds); + this.date_ = new Date(getMsUTC(d, timezone)); + } else { + this.date_ = new Date(year, month, day, hours, minutes, seconds, milliseconds); + } } - else - this.date_ = new Date(year, month, day, hours, minutes, seconds, milliseconds); - - if (tizen.time.getAvailableTimezones().indexOf(this.timezone_) < 0) - throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR); }; -function getTimezoneOffset(_timezone, _timeInMs) { - var result = native_.callSync('Time_getTimeZoneOffset', { - timezone: _timezone, - value: _timeInMs - }); - if (native_.isFailure(result)) { - throw native_.getErrorObject(result); - } - - return native_.getResultObject(result); -} - -function _getTimeWithOffset(date) { - var OffsetInMilliseconds = date.getTimezoneOffset() * _minuteInMilliseconds * -1; - return date.getTime() + OffsetInMilliseconds; -} - tizen.TZDate.prototype.getDate = function() { return this.date_.getDate(); }; @@ -356,7 +397,9 @@ tizen.TZDate.prototype.setFullYear = function() { }; tizen.TZDate.prototype.getHours = function() { - return this.date_.getHours(); + var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, + getMsUTC(this.date_)))); + return d.date_.getUTCHours(); }; tizen.TZDate.prototype.setHours = function() { @@ -422,7 +465,7 @@ tizen.TZDate.prototype.setSeconds = function() { tizen.TZDate.prototype.getUTCDate = function() { var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); + getMsUTC(this.date_)) * -1)); return d.getDate(); }; @@ -437,13 +480,13 @@ tizen.TZDate.prototype.setUTCDate = function() { tizen.TZDate.prototype.getUTCDay = function() { var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); + getMsUTC(this.date_)) * -1)); return d.getDay(); }; tizen.TZDate.prototype.getUTCFullYear = function() { var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); + getMsUTC(this.date_)) * -1)); return d.getFullYear(); }; @@ -457,9 +500,7 @@ tizen.TZDate.prototype.setUTCFullYear = function() { }; tizen.TZDate.prototype.getUTCHours = function() { - var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); - return d.getHours(); + return this.date_.getUTCHours(); }; tizen.TZDate.prototype.setUTCHours = function() { @@ -468,14 +509,14 @@ tizen.TZDate.prototype.setUTCHours = function() { type: types_.LONG }]); - var offset_hours = getTimezoneOffset(this.timezone_, _getTimeWithOffset(this.date_)) / + var offset_hours = getTimezoneOffset(this.timezone_, getMsUTC(this.date_)) / _hourInMilliseconds; this.date_.setHours(args.hours + offset_hours); }; tizen.TZDate.prototype.getUTCMilliseconds = function() { var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); + getMsUTC(this.date_)) * -1)); return d.getMilliseconds(); }; @@ -490,7 +531,7 @@ tizen.TZDate.prototype.setUTCMilliseconds = function() { tizen.TZDate.prototype.getUTCMinutes = function() { var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); + getMsUTC(this.date_)) * -1)); return d.getMinutes(); }; @@ -505,7 +546,7 @@ tizen.TZDate.prototype.setUTCMinutes = function() { tizen.TZDate.prototype.getUTCMonth = function() { var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); + getMsUTC(this.date_)) * -1)); return d.getMonth(); }; @@ -520,7 +561,7 @@ tizen.TZDate.prototype.setUTCMonth = function() { tizen.TZDate.prototype.getUTCSeconds = function() { var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_, - _getTimeWithOffset(this.date_)) * -1)); + getMsUTC(this.date_)) * -1)); return d.getSeconds(); }; @@ -736,7 +777,7 @@ tizen.TZDate.prototype.secondsFromUTC = function() { tizen.TZDate.prototype.isDST = function() { var result = native_.callSync('Time_isDST', { timezone: this.timezone_, - value: _getTimeWithOffset(this.date_) + value: getMsUTC(this.date_) }); if (native_.isFailure(result)) { return false; @@ -748,7 +789,7 @@ tizen.TZDate.prototype.isDST = function() { tizen.TZDate.prototype.getPreviousDSTTransition = function() { var result = native_.callSync('Time_getDSTTransition', { 'timezone': this.timezone_, - 'value': _getTimeWithOffset(this.date_), + 'value': getMsUTC(this.date_), 'trans': 'NEXT_TRANSITION' }); if (native_.isFailure(result)) { @@ -764,7 +805,7 @@ tizen.TZDate.prototype.getPreviousDSTTransition = function() { tizen.TZDate.prototype.getNextDSTTransition = function() { var result = native_.callSync('Time_getDSTTransition', { timezone: this.timezone_, - value: _getTimeWithOffset(this.date_), + value: getMsUTC(this.date_), trans: 'PREV_TRANSITION' }); if (native_.isFailure(result)) { diff --git a/src/time/time_instance.cc b/src/time/time_instance.cc index c170780d..297cef37 100644 --- a/src/time/time_instance.cc +++ b/src/time/time_instance.cc @@ -74,6 +74,7 @@ TimeInstance::TimeInstance() { TimeSetTimezoneChangeListener); REGISTER_SYNC("Time_unsetTimezoneChangeListener", TimeUnsetTimezoneChangeListener); + REGISTER_SYNC("Time_getMsUTC", TimeGetMsUTC); #undef REGISTER_SYNC #undef REGISTER_ASYNC @@ -149,27 +150,17 @@ void TimeInstance::TimeGetTimeZoneOffset(const JsonValue& args, UErrorCode ec = U_ZERO_ERROR; std::unique_ptr timezone(TimeZone::createTimeZone(*id)); - std::unique_ptr cal(Calendar::createInstance(*timezone, ec)); - if (U_FAILURE(ec)) { - LoggerE("Failed to create Calendar instance"); - ReportError(out); - return; - } - cal->setTime(dateInMs, ec); + int32_t rawOffset = 0; + int32_t dstOffset = 0; + timezone->getOffset(dateInMs, false, rawOffset, dstOffset, ec); if (U_FAILURE(ec)) { - LoggerE("Failed to set time"); + LoggerE("Failed to get timezone offset"); ReportError(out); return; } - - int32_t offset = timezone->getRawOffset(); - - if (cal->inDaylightTime(ec)) offset += _hourInMilliseconds; - std::stringstream offsetStr; - offsetStr << offset; - + offsetStr << (rawOffset + dstOffset); ReportSuccess(JsonValue(offsetStr.str()), out); } @@ -188,8 +179,8 @@ void TimeInstance::TimeGetTimeZoneAbbreviation(const JsonValue& args, } UErrorCode ec = U_ZERO_ERROR; - std::unique_ptr cal( - Calendar::createInstance(TimeZone::createTimeZone(*id), ec)); + std::unique_ptr timezone(TimeZone::createTimeZone(*id)); + std::unique_ptr cal(Calendar::createInstance(*timezone, ec)); if (U_FAILURE(ec)) { LoggerE("Failed to create Calendar instance"); ReportError(out); @@ -232,7 +223,6 @@ void TimeInstance::TimeIsDST(const JsonValue& args, JsonObject& out) { std::unique_ptr id( new UnicodeString(args.get("timezone").to_str().c_str())); UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL); - dateInMs -= _hourInMilliseconds; if (errno == ERANGE) { LoggerE("Value out of range"); @@ -241,22 +231,17 @@ void TimeInstance::TimeIsDST(const JsonValue& args, JsonObject& out) { } UErrorCode ec = U_ZERO_ERROR; - std::unique_ptr cal( - Calendar::createInstance(TimeZone::createTimeZone(*id), ec)); - if (U_FAILURE(ec)) { - LoggerE("Failed to create Calendar instance"); - ReportError(out); - return; - } + std::unique_ptr timezone(TimeZone::createTimeZone(*id)); - cal->setTime(dateInMs, ec); + int32_t rawOffset = 0; + int32_t dstOffset = 0; + timezone->getOffset(dateInMs, false, rawOffset, dstOffset, ec); if (U_FAILURE(ec)) { - LoggerE("Failed to set time"); + LoggerE("Failed to get timezone offset"); ReportError(out); return; } - - ReportSuccess(JsonValue{static_cast(cal->inDaylightTime(ec))}, out); + ReportSuccess(JsonValue{static_cast(dstOffset)}, out); } void TimeInstance::TimeGetDSTTransition(const JsonValue& args, @@ -348,8 +333,8 @@ bool TimeInstance::toStringByFormat(const JsonValue& args, JsonValue& out, } UErrorCode ec = U_ZERO_ERROR; - std::unique_ptr cal( - Calendar::createInstance(TimeZone::createTimeZone(*id), ec)); + std::unique_ptr timezone(TimeZone::createTimeZone(*id)); + std::unique_ptr cal(Calendar::createInstance(*timezone, ec)); if (U_FAILURE(ec)) { LoggerE("Failed to create Calendar instance"); return false; @@ -690,5 +675,33 @@ void TimeInstance::TimeUnsetTimezoneChangeListener(const JsonValue& /*args*/, ReportSuccess(out); } +void TimeInstance::TimeGetMsUTC(const JsonValue& args, JsonObject& out) { + LoggerD("Entered"); + + std::unique_ptr id(new UnicodeString(args.get("timezone").to_str().c_str())); + UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL); + if (errno == ERANGE) { + LoggerE("Value out of range"); + ReportError(out); + return; + } + + UErrorCode ec = U_ZERO_ERROR; + std::unique_ptr timezone(TimeZone::createTimeZone(*id)); + + int32_t rawOffset = 0; + int32_t dstOffset = 0; + timezone->getOffset(dateInMs, true, rawOffset, dstOffset, ec); + if (U_FAILURE(ec)) { + LoggerE("Failed to get timezone offset"); + ReportError(out); + return; + } + + dateInMs -= (rawOffset + dstOffset); + + ReportSuccess(JsonValue{static_cast(dateInMs)}, out); +} + } // namespace time } // namespace extension diff --git a/src/time/time_instance.h b/src/time/time_instance.h index ec4c5595..6cb1e1ed 100644 --- a/src/time/time_instance.h +++ b/src/time/time_instance.h @@ -48,6 +48,7 @@ class TimeInstance : public common::ParsedInstance { void TimeUnsetDateTimeChangeListener(const JsonValue& args, JsonObject& out); void TimeSetTimezoneChangeListener(const JsonValue& args, JsonObject& out); void TimeUnsetTimezoneChangeListener(const JsonValue& args, JsonObject& out); + void TimeGetMsUTC(const JsonValue& args, JsonObject& out); UnicodeString getDateTimeFormat(DateTimeFormatType type, bool bLocale); bool toStringByFormat(const JsonValue& args, JsonValue& out, diff --git a/src/utils/utils_api.js b/src/utils/utils_api.js index 6020012c..cdb563ff 100755 --- a/src/utils/utils_api.js +++ b/src/utils/utils_api.js @@ -43,9 +43,13 @@ DateConverter.prototype.fromTZDate = function(v) { return v; } - var utc = v.toUTC(); - var timestamp = new Date(utc.getFullYear(), utc.getMonth(), utc.getDate(), utc.getHours(), - utc.getMinutes(), utc.getSeconds()) / 1000; + var timestamp = Date.UTC(v.date_.getUTCFullYear(), + v.date_.getUTCMonth(), + v.date_.getUTCDate(), + v.date_.getUTCHours(), + v.date_.getUTCMinutes(), + v.date_.getUTCSeconds(), + v.date_.getUTCMilliseconds()) / 1000; return { year: v.getFullYear(), -- 2.34.1