Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/bug-1103115 into lp:zorba.
Commit message: Corrected time-zone units and did a clean-up of the TimeZone class. Requested reviews: Paul J. Lucas (paul-lucas) Related bugs: Bug #1103115 in Zorba: "Timezone units as hours are wrong" https://bugs.launchpad.net/zorba/+bug/1103115 For more details, see: https://code.launchpad.net/~zorba-coders/zorba/bug-1103115/+merge/165002 Corrected time-zone units and did a clean-up of the TimeZone class. -- https://code.launchpad.net/~zorba-coders/zorba/bug-1103115/+merge/165002 Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'include/zorba/dynamic_context.h' --- include/zorba/dynamic_context.h 2013-03-13 16:17:38 +0000 +++ include/zorba/dynamic_context.h 2013-05-22 02:24:29 +0000 @@ -213,7 +213,7 @@ * or dateTime value that does not have a timezone is used in a comparison or * arithmetic operation. * - * @param aTimezone the implicit timezone as int that should be used. + * @param aTimezone the number of seconds east of the prime meridian. * @return true if the implicit timezone has been set successfully, false otherwise. * @throw ZorbaException if an error occured. */ @@ -223,8 +223,9 @@ /** \brief Retrieve the implicit timezone used in comparisons or arithmetic operations * of date, time, or dateTime values. * - * @return int the implicit timezone. Note that 0 is returned if an error occured - * and an DiagnosticHandler is used. + * @return the implicit timezone as the number of seconds east of the + * prime medidian. Note that 0 is returned if an error occured and an + * DiagnosticHandler is used. * @throw ZorbaException if an error occured. */ virtual int === modified file 'include/zorba/item_factory.h' --- include/zorba/item_factory.h 2013-04-17 00:24:24 +0000 +++ include/zorba/item_factory.h 2013-05-22 02:24:29 +0000 @@ -327,13 +327,13 @@ * @param aHour short-valued representation of the hour. * @param aMinute short-valued representation of the minute. * @param aSecond double-valued representation of the seconds and fractional seconds. - * @param aTimeZone_hours short-valued representation of the difference in hours to UTC. + * @param aTimeZone the number of seconds east of the prime meridian. * @return The DateTime Item. */ virtual Item createDateTime(short aYear, short aMonth, short aDay, short aHour, short aMinute, double aSecond, - short aTimeZone_hours) = 0; + int aTimeZone) = 0; /** \brief Creates a DateTime Item without setting a time zone. * see [http://www.w3.org/TR/xmlschema-2/#dateTime] @@ -615,11 +615,11 @@ * @param aHour short representation of the hour. * @param aMinute short representation of the minute. * @param aSecond double representation of the seconds and fractional seconds. - * @param aTimeZone_hours short representation of the timezone difference in hours to UTC. + * @param aTimeZone the number of seconds east of the prime meridian. * @return The Time Item. */ virtual Item - createTime ( short aHour, short aMinute, double aSecond, short aTimeZone_hours ) = 0; + createTime ( short aHour, short aMinute, double aSecond, int aTimeZone ) = 0; /** \brief Creates an Unsigned Byte Item * see [http://www.w3.org/TR/xmlschema-2/#unsignedByte] @@ -848,13 +848,13 @@ * @param aHour short-valued representation of the hour. * @param aMinute short-valued representation of the minute. * @param aSecond double-valued representation of the seconds and fractional seconds. - * @param aTimeZone_hours short-valued representation of the difference in hours to UTC. + * @param aTimeZone the number of seconds east of the prime meridian. * @return The DateTimeStamp Item. */ virtual Item createDateTimeStamp(short aYear, short aMonth, short aDay, short aHour, short aMinute, double aSecond, - short aTimeZone_hours) = 0; + int aTimeZone) = 0; /** \brief Creates a DateTimeStamp Item * see [www.w3.org/TR/xmlschema11-2/#dateTimeStamp] === modified file 'src/api/itemfactoryimpl.cpp' --- src/api/itemfactoryimpl.cpp 2013-05-15 23:22:01 +0000 +++ src/api/itemfactoryimpl.cpp 2013-05-22 02:24:29 +0000 @@ -402,11 +402,11 @@ Item ItemFactoryImpl::createDateTime(short aYear, short aMonth, short aDay, short aHour, short aMinute, double aSecond, - short aTimezone_hours) + int aTimezone) { store::Item_t lItem; theItemFactory->createDateTime(lItem, aYear, aMonth, aDay, - aHour, aMinute, aSecond, aTimezone_hours); + aHour, aMinute, aSecond, aTimezone); return &*lItem; } @@ -439,11 +439,11 @@ Item ItemFactoryImpl::createDateTimeStamp(short aYear, short aMonth, short aDay, short aHour, short aMinute, double aSecond, - short aTimezone_hours) + int aTimezone) { store::Item_t lItem; theItemFactory->createDateTimeStamp(lItem, aYear, aMonth, aDay, - aHour, aMinute, aSecond, aTimezone_hours); + aHour, aMinute, aSecond, aTimezone); return &*lItem; } @@ -747,12 +747,10 @@ short aHour, short aMinute, double aSecond, - short aTimezone_hours ) + int aTimezone ) { store::Item_t lItem; - - theItemFactory->createTime(lItem, aHour, aMinute, aSecond, aTimezone_hours ); - + theItemFactory->createTime(lItem, aHour, aMinute, aSecond, aTimezone ); return &*lItem; } === modified file 'src/api/itemfactoryimpl.h' --- src/api/itemfactoryimpl.h 2013-03-27 20:01:19 +0000 +++ src/api/itemfactoryimpl.h 2013-05-22 02:24:29 +0000 @@ -129,7 +129,7 @@ virtual Item createDateTime(short aYear, short aMonth, short aDay, short aHour, short aMinute, double aSecond, - short aTimezone_hours); + int aTimezone); virtual Item createDateTime(short aYear, short aMonth, short aDay, @@ -141,7 +141,7 @@ virtual Item createDateTimeStamp(short aYear, short aMonth, short aDay, short aHour, short aMinute, double aSecond, - short aTimezone_hours); + int aTimezone); virtual Item createDateTimeStamp( const String& aDateTimeStampValue ); @@ -226,7 +226,7 @@ createTime ( short aHour, short aMinute, double aSecond ); virtual Item - createTime ( short aHour, short aMinute, double aSecond, short aTimezone_hours ); + createTime ( short aHour, short aMinute, double aSecond, int aTimezone); virtual Item createUnsignedByte(const unsigned char aValue); === modified file 'src/runtime/durations_dates_times/format_dateTime.cpp' --- src/runtime/durations_dates_times/format_dateTime.cpp 2013-05-08 01:05:04 +0000 +++ src/runtime/durations_dates_times/format_dateTime.cpp 2013-05-22 02:24:29 +0000 @@ -382,7 +382,7 @@ // +00:00, A = +01:00, B = +02:00, ..., M = +12:00, N = -01:00, O = // -02:00, ... Y = -12:00. // - if ( tz.timeZoneNotSet() ) { + if ( !tz ) { // // Ibid: The letter J (meaning local time) is used in the case of a // value that does not specify a timezone offset. @@ -429,7 +429,7 @@ break; } - if ( tz.isNegative() ) + if ( tz < 0 ) tmp += '-', hour = std::abs( hour ); else tmp += '+'; === modified file 'src/store/api/item_factory.h' --- src/store/api/item_factory.h 2013-05-16 02:55:43 +0000 +++ src/store/api/item_factory.h 2013-05-22 02:24:29 +0000 @@ -402,7 +402,8 @@ * @param hour * @param minute * @param second - * @param timeZone_hours Difference in hours to UTC + * @param tz_sec Timezone offset where positive numbers are seconds east of + * the prime meridian. */ virtual bool createDateTime( Item_t& result, @@ -412,7 +413,7 @@ short hour, short minute, double second, - short timeZone_hours) = 0; + int tz_sec) = 0; /** * Specification: [http://www.w3.org/TR/xmlschema-2/#dateTime] @@ -446,7 +447,8 @@ * @param hour * @param minute * @param second - * @param timeZone_hours Difference in hours to UTC + * @param tz_sec Timezone offset where positive numbers are seconds east of + * the prime meridian. */ virtual bool createDateTimeStamp( Item_t& result, @@ -456,7 +458,7 @@ short hour, short minute, double second, - short timeZone_hours) = 0; + int tz_sec) = 0; /** * Specification: [http://www.w3.org/TR/xmlschema11-2/#dateTimeStamp] @@ -510,14 +512,15 @@ * @param hour * @param minute * @param second - * @param timeZone_hours Difference in hours to UTC + * @param tz_sec Timezone offset where positive numbers are seconds east of + * the prime meridian. */ virtual bool createTime( Item_t& result, short hour, short minute, double second, - short timeZone_hours) = 0; + int tz_sec) = 0; virtual bool createGDay(Item_t& result, const xs_gDay* value) = 0; === modified file 'src/store/naive/simple_item_factory.cpp' --- src/store/naive/simple_item_factory.cpp 2013-05-16 18:25:17 +0000 +++ src/store/naive/simple_item_factory.cpp 2013-05-22 02:24:29 +0000 @@ -520,10 +520,10 @@ short hour, short minute, double second, - short timeZone_hours) + int tz_sec) { DateTime dt; - TimeZone tz(timeZone_hours); + TimeZone tz(tz_sec); if (DateTime::createDateTime(year, month, day, hour, minute, second, &tz, dt) == 0) { @@ -624,10 +624,10 @@ short hour, short minute, double second, - short timeZone_hours) + int tz_sec) { DateTime dt; - TimeZone tz(timeZone_hours); + TimeZone tz(tz_sec); if (DateTime::createDateTime(year, month, day, hour, minute, second, &tz, dt) == 0) { @@ -791,10 +791,10 @@ short hour, short minute, double second, - short timeZone_hours) + int tz_sec) { DateTime dt; - TimeZone tz(timeZone_hours); + TimeZone tz(tz_sec); if(DateTime::createTime(hour, minute, second, &tz, dt) == 0) { === modified file 'src/store/naive/simple_item_factory.h' --- src/store/naive/simple_item_factory.h 2013-05-16 02:55:43 +0000 +++ src/store/naive/simple_item_factory.h 2013-05-22 02:24:29 +0000 @@ -184,7 +184,7 @@ bool createDateTime(store::Item_t& result, short year, short month, short day, short hour, short minute, double second); - bool createDateTime(store::Item_t& result, short year , short month, short day, short hour, short minute, double second, short timeZone_hours); + bool createDateTime(store::Item_t& result, short year , short month, short day, short hour, short minute, double second, int tz_sec); bool createDateTime(store::Item_t& result, const char* str, ulong strlen); @@ -194,7 +194,7 @@ bool createDateTimeStamp(store::Item_t& result, const xs_dateTime* value); - bool createDateTimeStamp(store::Item_t& result, short year , short month, short day, short hour, short minute, double second, short timeZone_hours); + bool createDateTimeStamp(store::Item_t& result, short year , short month, short day, short hour, short minute, double second, int tz_sec); bool createDateTimeStamp(store::Item_t& result, const char* str, ulong strlen); @@ -212,7 +212,7 @@ bool createTime(store::Item_t& result, short hour, short minute, double second ); - bool createTime(store::Item_t& result, short hour, short minute, double second, short timeZone_hours); + bool createTime(store::Item_t& result, short hour, short minute, double second, int tz_sec); bool createGDay(store::Item_t& result, const xs_gDay* value); === modified file 'src/util/hash/hash.h' --- src/util/hash/hash.h 2013-04-17 05:02:24 +0000 +++ src/util/hash/hash.h 2013-05-22 02:24:29 +0000 @@ -95,6 +95,7 @@ */ template<typename T> struct hash : std::unary_function<T,size_t> { + hash() { } size_t operator()( T ) const; // not defined }; @@ -120,6 +121,7 @@ */ template<typename T> struct hash : unary_function<T,size_t> { + hash() { } size_t operator()( T ) const; // not defined }; === modified file 'src/zorbaserialization/serialize_zorba_types.cpp' --- src/zorbaserialization/serialize_zorba_types.cpp 2013-05-15 23:22:01 +0000 +++ src/zorbaserialization/serialize_zorba_types.cpp 2013-05-22 02:24:29 +0000 @@ -150,8 +150,8 @@ ********************************************************************************/ void operator&(Archiver& ar, TimeZone& obj) { - ar & static_cast<Duration&>(obj); - ar & obj.timezone_not_set; + ar & obj.gmtoff_; + ar & obj.timezone_not_set_; } === modified file 'src/zorbatypes/CMakeLists.txt' --- src/zorbatypes/CMakeLists.txt 2013-05-15 23:22:01 +0000 +++ src/zorbatypes/CMakeLists.txt 2013-05-22 02:24:29 +0000 @@ -22,7 +22,8 @@ URI.cpp collation_manager.cpp chartype.cpp - rchandle.cpp) + rchandle.cpp + timezone.cpp) IF (NOT ZORBA_NO_FULL_TEXT) LIST(APPEND ZORBATYPES_SRCS ft_token.cpp) === modified file 'src/zorbatypes/datetime/CMakeLists.txt' --- src/zorbatypes/datetime/CMakeLists.txt 2013-02-07 17:24:36 +0000 +++ src/zorbatypes/datetime/CMakeLists.txt 2013-05-22 02:24:29 +0000 @@ -11,8 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + SET(DATETIME_SRCS duration.cpp - datetimetype.cpp - timezone.cpp - parse.cpp) + datetimetype.cpp + parse.cpp) === modified file 'src/zorbatypes/datetime/datetimetype.cpp' --- src/zorbatypes/datetime/datetimetype.cpp 2013-05-09 00:21:51 +0000 +++ src/zorbatypes/datetime/datetimetype.cpp 2013-05-22 02:24:29 +0000 @@ -94,9 +94,8 @@ const DateTime* time, DateTime& result) { - if (!date->getTimezone().timeZoneNotSet() && - !time->getTimezone().timeZoneNotSet() && - !(date->getTimezone() == time->getTimezone())) + if (date->getTimezone() && time->getTimezone() && + date->getTimezone() != time->getTimezone()) return 2; int res = createDateTime(date->getYear(), @@ -110,9 +109,9 @@ if (res == 0) { - if (!date->getTimezone().timeZoneNotSet()) + if (date->getTimezone()) result.the_time_zone = date->getTimezone(); - else if (!time->getTimezone().timeZoneNotSet()) + else if (time->getTimezone()) result.the_time_zone = time->getTimezone(); } @@ -388,9 +387,9 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, - len - pos, - dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, + len - pos, + &dt.the_time_zone))) return err; } @@ -435,7 +434,7 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, len - pos, &dt.the_time_zone))) return err; } @@ -471,7 +470,7 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, len - pos, &dt.the_time_zone))) return err; } @@ -529,7 +528,7 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, len - pos, &dt.the_time_zone))) return err; } @@ -585,7 +584,7 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, len - pos, &dt.the_time_zone))) return err; } @@ -637,7 +636,7 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, len - pos, &dt.the_time_zone))) return err; } @@ -690,7 +689,7 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, len - pos, &dt.the_time_zone))) return err; } @@ -743,7 +742,7 @@ if (pos < len) { - if ((err = TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))) + if ((err = TimeZone::parse(str + pos, len - pos, &dt.the_time_zone))) return err; } @@ -1040,7 +1039,7 @@ bool DateTime::hasTimezone() const { - return !the_time_zone.timeZoneNotSet(); + return !!the_time_zone; } @@ -1097,7 +1096,7 @@ hval = hashfun::h32<int>(dt->data[SECONDS_DATA], hval); hval = hashfun::h32<int>(dt->data[FRACSECONDS_DATA], hval); - hval = dt->the_time_zone.hash(hval); + hval ^= dt->the_time_zone.hash(); return hval; } @@ -1239,7 +1238,7 @@ DateTime* dt; Duration d; - if( the_time_zone.timeZoneNotSet() ) + if( !the_time_zone ) { // validate timezone value (-14 .. +14 H) if (tz_seconds > 14*3600 || tz_seconds < -14*3600) @@ -1278,27 +1277,31 @@ // If $arg does not have a timezone component and $timezone is not the empty sequence, // then the result is $arg with $timezone as the timezone component. - if (the_time_zone.timeZoneNotSet()) + if ( !the_time_zone ) { - if (TimeZone::createTimeZone(context_tz->getHours(), context_tz->getMinutes(), context_tz->getIntSeconds(), dt->the_time_zone)) - assert(0); + dt->the_time_zone = TimeZone( + context_tz->getHours(), + context_tz->getMinutes() + ); } else { // If $arg has a timezone component and $timezone is not the empty sequence, then // the result is an xs:dateTime value with a timezone component of $timezone that is equal to $arg. dtduration = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET, - the_time_zone.isNegative(), + the_time_zone < 0, 0, 0, 0, the_time_zone.getHours(), the_time_zone.getMinutes(), - the_time_zone.getIntSeconds(), + 0, 0)); dtduration = std::auto_ptr<Duration>(*context_tz - *dtduration); dt = std::auto_ptr<DateTime>(dt->addDuration(*dtduration)); - if (TimeZone::createTimeZone(context_tz->getHours(), context_tz->getMinutes(), context_tz->getIntSeconds(), dt->the_time_zone)) - assert(0); + dt->the_time_zone = TimeZone( + context_tz->getHours(), + context_tz->getMinutes() + ); } return dt.release(); @@ -1318,7 +1321,7 @@ if (d == NULL) { - if (!the_time_zone.timeZoneNotSet()) + if ( the_time_zone ) dt->the_time_zone = TimeZone(); } else @@ -1334,21 +1337,20 @@ // If $arg does not have a timezone component and $timezone is not the // empty sequence, then the result is $arg with $timezone as the timezone // component. - if (the_time_zone.timeZoneNotSet()) + if ( !the_time_zone ) { - if (TimeZone::createTimeZone(d->getHours(), d->getMinutes(), d->getIntSeconds(), dt->the_time_zone)) - assert(0); + dt->the_time_zone = TimeZone( d->getHours(), d->getMinutes() ); } else { // If $arg has a timezone component and $timezone is not the empty sequence, then // the result is an xs:dateTime value with a timezone component of $timezone that is equal to $arg. dtduration = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET, - the_time_zone.isNegative(), + the_time_zone < 0, 0, 0, 0, the_time_zone.getHours(), the_time_zone.getMinutes(), - the_time_zone.getIntSeconds(), + 0, 0)); context_tz = std::auto_ptr<Duration>(new Duration(*d)); @@ -1358,11 +1360,10 @@ dtduration = std::auto_ptr<Duration>(*context_tz - *dtduration); dt.reset(dt->addDuration(*dtduration)); - if (TimeZone::createTimeZone(context_tz->getHours(), - context_tz->getMinutes(), - context_tz->getIntSeconds(), - dt->the_time_zone)) - assert(0); + dt->the_time_zone = TimeZone( + context_tz->getHours(), + context_tz->getMinutes() + ); } } === modified file 'src/zorbatypes/datetime/duration.cpp' --- src/zorbatypes/datetime/duration.cpp 2013-05-15 23:22:01 +0000 +++ src/zorbatypes/datetime/duration.cpp 2013-05-22 02:24:29 +0000 @@ -419,15 +419,14 @@ int Duration::fromTimezone(const TimeZone& t, Duration& d) { - if(!t.timeZoneNotSet()) + if( t ) { d = Duration(DAYTIMEDURATION_FACET, - t.isNegative(), + t < 0, 0, 0, 0, t.getHours(), t.getMinutes(), - t.getIntSeconds(), - t.getFractionalSeconds() ); + 0, 0 ); return 0; } else === renamed file 'src/zorbatypes/datetime/timezone.cpp' => 'src/zorbatypes/timezone.cpp' --- src/zorbatypes/datetime/timezone.cpp 2013-05-09 00:21:51 +0000 +++ src/zorbatypes/timezone.cpp 2013-05-22 02:24:29 +0000 @@ -1,12 +1,12 @@ /* * Copyright 2006-2008 The FLWOR Foundation. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,191 +15,141 @@ */ #include "stdafx.h" +// standard #include <cstdlib> -#include <string> #include <exception> -#include <zorbatypes/timezone.h> - -#include "zorbatypes/datetime/parse.h" -#include "zorbatypes/decimal.h" - -#include "zorbautils/hashfun.h" - +// Zorba +#include "datetime/parse.h" +#include "timezone.h" #include "util/ascii_util.h" - - -namespace zorba -{ - - -TimeZone::TimeZone(short hours) : Duration(DAYTIMEDURATION_FACET) -{ - timezone_not_set = false; - - if (hours < 0) - is_negative = true; - - data[HOUR_DATA] = std::abs(hours); -} - - -int TimeZone::parseTimeZone(const char* str, ascii::size_type strlen, TimeZone& tz) -{ - ascii::size_type pos = 0; - - ascii::skip_space(str, strlen, &pos); - - // A time zone is of form: (('+' | '-') hh ':' mm) | 'Z' - - if (str[pos] == 'Z') - { - ++pos; - ascii::skip_space(str, strlen, &pos); - - if (pos != strlen) - return 1; - - // '+00:00', '-00:00', and 'Z' all represent the same zero-length duration - // timezone, UTC; 'Z' is its canonical representation. - tz = TimeZone(0); - } - else - { - tz = TimeZone(0); - - if (str[pos] == '-') - tz.is_negative = true; - else if (str[pos] == '+') - /* do nothing */ ; - else - return 1; - - ++pos; - - if ( parse_long(str, strlen, pos, tz.data[HOUR_DATA], 2, 2) ) - return 1; - - if (str[pos++] != ':') - return 1; - - if ( parse_long(str, strlen, pos, tz.data[MINUTE_DATA], 2, 2) ) - return 1; - - // minutes must be between 00..59 - if (tz.data[MINUTE_DATA] >= 60) - return 1; - - // hours must be between -14 .. 14 - if (tz.data[HOUR_DATA]*60 + tz.data[MINUTE_DATA] > 14*60) - return 1; - - ascii::skip_space(str, strlen, &pos); - - if (pos != strlen) - return 1; - } - - return 0; -} - - -int TimeZone::createTimeZone(int hours, int minutes, int seconds, TimeZone& tz) -{ - tz = TimeZone(hours); - tz.data[MINUTE_DATA] = std::abs(minutes); - tz.data[SECONDS_DATA] = std::abs(seconds); - if ( minutes < 0 || seconds < 0 ) // hours is checked in TimeZone() ctor - tz.is_negative = true; - tz.normalize(); - return 0; -} - - -bool TimeZone::operator<(const TimeZone& t) const -{ - return (compare(t) == -1); -} - - -bool TimeZone::operator==(const TimeZone& t) const -{ - return (compare(t) == 0); -} - - -zstring TimeZone::toString() const -{ +#include "util/hash/hash.h" +#include "util/string_util.h" + +using namespace std; + +namespace zorba { + +/////////////////////////////////////////////////////////////////////////////// + +/** + * XML Schema Part 2: 3.2.7.3: Timezones are durations with ... the hour + * magnitude limited to at most 14 ... + */ +static int const MaxHour = 14; + +static TimeZone::value_type const MaxValue = MaxHour * 60 * 60; +static TimeZone::value_type const MinValue = -MaxValue; + +static TimeZone::value_type check_value( TimeZone::value_type gmtoff ) { + if ( gmtoff < MinValue ) + throw range_error( + BUILD_STRING( gmtoff, ": value < minimum value of ", MinValue ) + ); + if ( gmtoff > MaxValue ) + throw range_error( + BUILD_STRING( gmtoff, ": value > maximum value of ", MaxValue ) + ); + return gmtoff; +} + +static TimeZone::value_type check_value( int hours, int minutes ) { + bool const negative = hours < 0 || minutes < 0; + + if ( (hours = ::abs( hours )) > MaxHour ) + throw range_error( + BUILD_STRING( hours, ": |hours| > maximum of ", MaxHour ) + ); + if ( (minutes = ::abs( minutes )) > 59 ) + throw range_error( + BUILD_STRING( minutes, ": |minutes| > maximum of 59" ) + ); + if ( hours == MaxHour && minutes ) + throw range_error( + BUILD_STRING( minutes, ": |minutes| > 0 when |hours| is ", MaxHour ) + ); + + return (hours * 60 * 60 + minutes * 60) * (negative ? -1 : 1); +} + +/////////////////////////////////////////////////////////////////////////////// + +TimeZone::TimeZone( int gmtoff ) : + gmtoff_( check_value( gmtoff ) ), + timezone_not_set_( false ) +{ +} + +TimeZone::TimeZone( int hours, int minutes ) : + gmtoff_( check_value( hours, minutes ) ), + timezone_not_set_( false ) +{ +} + +size_t TimeZone::hash() const { + std::hash<value_type> const hasher; + return !*this ? hasher( ~0 ) : hasher( gmtoff_ ); +} + +int TimeZone::parse( char const *s, size_t s_len, TimeZone *tz ) { + s = ascii::trim_space( s, &s_len ); + char const *const end = s + s_len; + if ( s == end ) // string was entirely whitespace + return 1; + + // + // Ibid: The lexical representation of a timezone is a string of the form: + // (('+' | '-') hh ':' mm) | 'Z'. + // + if ( *s == 'Z' ) { + if ( ++s != end ) + return 1; + *tz = TimeZone( 0 ); + } else { + if ( end - s != 6 ) // need exactly 6 characters + return 1; + switch ( *s ) { + case '+': // aton will parse the '+' or '-' + case '-': + break; + default: + return 1; + } + try { + int const hours = ztd::aton<int>( s, end, &s ); + if ( s == end || *s != ':' ) + return 1; + int const minutes = ztd::aton<unsigned>( s, end, &s ); + if ( s != end ) + return 1; + *tz = TimeZone( hours, minutes ); + } + catch ( std::invalid_argument const& ) { + return 1; + } + catch ( std::range_error const& ) { + return 2; + } + } + return 0; +} + +zstring TimeZone::toString() const { zstring result; - - if (timeZoneNotSet()) - return result; - - if (data[HOUR_DATA] == 0 && data[MINUTE_DATA] == 0) - return "Z"; - - result += isNegative() ? '-' : '+'; - result += zero_pad(data[HOUR_DATA], 2); - result += ':'; - result += zero_pad(data[MINUTE_DATA], 2); - + if ( *this ) { + if ( !gmtoff_ ) + result = 'Z'; + else { + result += *this < 0 ? '-' : '+'; + result += zero_pad( std::abs( getHours() ), 2 ); + result += ':'; + result += zero_pad( std::abs( getMinutes() ), 2 ); + } + } return result; } - -int TimeZone::compare(const TimeZone& t) const -{ - return Duration::compare(t); -} - - -bool TimeZone::timeZoneNotSet() const -{ - return timezone_not_set; -} - - -bool TimeZone::isNegative() const -{ - return Duration::isNegative(); -} - - -long TimeZone::getHours() const -{ - return Duration::getHours(); -} - - -long TimeZone::getMinutes() const -{ - return Duration::getMinutes(); -} - - -xs_decimal TimeZone::getSeconds() const -{ - return Duration::getSeconds(); -} - - -long TimeZone::getIntSeconds() const -{ - return Duration::getIntSeconds(); -} - - -long TimeZone::getFractionalSeconds() const -{ - return Duration::getFractionalSeconds(); -} - - -uint32_t TimeZone::hash(int implicit_timezone_seconds) const -{ - return hashfun::h32<uint32_t>(timeZoneNotSet() ? (uint32_t)-1 : Duration::hash(), 0); -} - +/////////////////////////////////////////////////////////////////////////////// } // namespace zorba /* vim:set et sw=2 ts=2: */ === modified file 'src/zorbatypes/timezone.h' --- src/zorbatypes/timezone.h 2013-05-08 20:14:47 +0000 +++ src/zorbatypes/timezone.h 2013-05-22 02:24:29 +0000 @@ -17,77 +17,180 @@ #ifndef ZORBA_TIMEZONE_H #define ZORBA_TIMEZONE_H -#include <zorba/config.h> -#include "zorbatypes/zorbatypes_decl.h" -#include "zorbatypes/duration.h" -#include "util/ascii_util.h" - - -namespace zorba -{ +// standard +#include <iostream> + +// Zorba +#include <zorba/internal/ztd.h> +#include "zorbatypes/zstring.h" + +namespace zorba { class TimeZone; -namespace serialization -{ +namespace serialization { class Archiver; - void operator&(Archiver& ar, TimeZone& obj); + void operator&( Archiver&, TimeZone& ); } - -class TimeZone : protected Duration -{ - friend void serialization::operator&(serialization::Archiver& ar, TimeZone& obj); - -protected: - bool timezone_not_set; - -public: - /** - * Returns 0 on success. - */ - static int parseTimeZone(const char* str, ascii::size_type strlen, TimeZone& tz); - - /** - * Returns 0 on success. - */ - static int createTimeZone(int hours, int minutes, int seconds, TimeZone& tz); - -public: - ~TimeZone() { }; - - TimeZone() : timezone_not_set(true) { }; +/////////////////////////////////////////////////////////////////////////////// + +class TimeZone { + typedef internal::ztd::explicit_bool explicit_bool; +public: + typedef int value_type; + + /** + * Parses a %TimeZone. + * + * @param s The string to parse. Leading and trailing whitespce is ignored. + * @param s_len The number of characters to parse. + * @param tz The %TimeZone result. + * @return Returns 0 on success, 1 for an invalid format, 2 for out-of-range + * values. + */ + static int parse( char const *s, size_t s_len, TimeZone *tz ); + + /** + * Constructs a %TimeZone. + */ + TimeZone(); - TimeZone(short hours); - - bool operator<(const TimeZone& t) const; - - bool operator==(const TimeZone& t) const; - - int compare(const TimeZone& t) const; + /** + * Constructs a %TimeZone. + * + * @param gmtoff The number of seconds east of the prime meridian. + * @throws range_error if |<em>gmtoff</em>| > 50400 (14 hours). + */ + TimeZone( value_type gmtoff ); + + /** + * Constructs a %TimeZone. + * + * @throws range_error if |<em>hours</em>| > 14, |<em>minutes</em>| > + * 59, or |<em>hours</em>| == 14 and |<em>minutes</em>| > 0. + */ + TimeZone( int hours, int minutes ); + + /** + * Gets the number of hours offset from GMT. + * + * @return Returns said hours where positive hours are hours east of the + * prime meridian. + */ + int getHours() const; + + /** + * Gets the number of minutes offset from GMT. + * + * @return Returns said minutes where positive minutes are minutes east of + * the prime meridian. + */ + int getMinutes() const; + + /** + * Gets the timezone offset from GMT. + * + * @return Returns the number of seconds east of the prime meridian. + */ + value_type gmtoff() const; + + /** + * Conversion to \c bool. + * + * @return Returns \c true only if the time-zone is set. + */ + operator explicit_bool::type() const; + + size_t hash() const; zstring toString() const; - bool isNegative() const; - - long getHours() const; - - long getMinutes() const; - - Decimal getSeconds() const; - - long getIntSeconds() const; - - long getFractionalSeconds() const; - - uint32_t hash(int implicit_timezone_seconds) const; - - bool timeZoneNotSet() const; +private: + value_type gmtoff_; + bool timezone_not_set_; + + friend void serialization::operator&( serialization::Archiver&, TimeZone& ); }; -} /* namespace zorba */ -#endif - +/////////////////////////////////////////////////////////////////////////////// + +inline TimeZone::TimeZone() : timezone_not_set_( true ) { +} + +inline int TimeZone::getHours() const { + return gmtoff_ / (60 * 60); +} + +inline int TimeZone::getMinutes() const { + return gmtoff_ % (60 * 60); +} + +inline TimeZone::value_type TimeZone::gmtoff() const { + return gmtoff_; +} + +inline TimeZone::operator explicit_bool::type() const { + return explicit_bool::value_of( !timezone_not_set_ ); +} + +inline bool operator==( TimeZone const &tz1, TimeZone const &tz2 ) { + return ( tz1 && tz2 && tz1.gmtoff() == tz2.gmtoff() ) + || ( !tz1 && !tz2 ); +} + +inline bool operator!=( TimeZone const &tz1, TimeZone const &tz2 ) { + return !(tz1 == tz2); +} + +inline bool operator<( TimeZone const &tz1, TimeZone const &tz2 ) { + return tz2 && tz2 && tz1.gmtoff() < tz2.gmtoff(); +} + +inline bool operator<=( TimeZone const &tz1, TimeZone const &tz2 ) { + return tz2 && tz2 && tz1.gmtoff() <= tz2.gmtoff(); +} + +inline bool operator>( TimeZone const &tz1, TimeZone const &tz2 ) { + return tz2 && tz2 && tz1.gmtoff() > tz2.gmtoff(); +} + +inline bool operator>=( TimeZone const &tz1, TimeZone const &tz2 ) { + return tz2 && tz2 && tz1.gmtoff() >= tz2.gmtoff(); +} + +inline bool operator==( TimeZone const &tz1, int tz2 ) { + return tz1 && tz1.gmtoff() == tz2; +} + +inline bool operator!=( TimeZone const &tz1, int tz2 ) { + return !(tz1 == tz2); +} + +inline bool operator<( TimeZone const &tz1, int tz2 ) { + return tz1 && tz1.gmtoff() < tz2; +} + +inline bool operator<=( TimeZone const &tz1, int tz2 ) { + return tz1 && tz1.gmtoff() <= tz2; +} + +inline bool operator>( TimeZone const &tz1, int tz2 ) { + return tz1 && tz1.gmtoff() > tz2; +} + +inline bool operator>=( TimeZone const &tz1, int tz2 ) { + return tz1 && tz1.gmtoff() >= tz2; +} + +inline std::ostream& operator<<( std::ostream &o, TimeZone const &tz ) { + return o << tz.toString(); +} + +/////////////////////////////////////////////////////////////////////////////// + +} // namespace zorba +#endif /* ZORBA_TIMEZONE_H */ /* * Local variables: * mode: c++
-- Mailing list: https://launchpad.net/~zorba-coders Post to : zorba-coders@lists.launchpad.net Unsubscribe : https://launchpad.net/~zorba-coders More help : https://help.launchpad.net/ListHelp