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>| &gt; 50400 (14 hours).
+   */
+  TimeZone( value_type gmtoff );
+
+  /**
+   * Constructs a %TimeZone.
+   *
+   * @throws range_error if |<em>hours</em>| &gt; 14, |<em>minutes</em>| &gt;
+   * 59, or |<em>hours</em>| == 14 and |<em>minutes</em>| &gt; 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

Reply via email to