You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vxquery.apache.org by pr...@apache.org on 2012/08/03 04:12:27 UTC

svn commit: r1368769 - in /incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery: datamodel/util/ runtime/functions/cast/

Author: prestonc
Date: Fri Aug  3 02:12:26 2012
New Revision: 1368769

URL: http://svn.apache.org/viewvc?rev=1368769&view=rev
Log:
Found many issues with date related functions primarily with how timezones were handled.

Modified:
    incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/datamodel/util/DateTime.java
    incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDateTimeOperation.java
    incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGDayOperation.java
    incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthDayOperation.java
    incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthOperation.java
    incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearMonthOperation.java
    incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearOperation.java

Modified: incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/datamodel/util/DateTime.java
URL: http://svn.apache.org/viewvc/incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/datamodel/util/DateTime.java?rev=1368769&r1=1368768&r2=1368769&view=diff
==============================================================================
--- incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/datamodel/util/DateTime.java (original)
+++ incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/datamodel/util/DateTime.java Fri Aug  3 02:12:26 2012
@@ -72,7 +72,7 @@ public class DateTime {
         if (month > FIELD_MAXS[DateTime.MONTH_FIELD_INDEX] || month < FIELD_MINS[DateTime.MONTH_FIELD_INDEX]) {
             return false;
         }
-        if (day > FIELD_MAXS[DateTime.DAY_FIELD_INDEX] || day < monthCheck[(int) (month - 1)]) {
+        if (day > monthCheck[(int) (month - 1)] || day < FIELD_MINS[DateTime.DAY_FIELD_INDEX]) {
             return false;
         }
         if (hour > FIELD_MAXS[DateTime.HOUR_FIELD_INDEX] || hour < FIELD_MINS[DateTime.HOUR_FIELD_INDEX]) {
@@ -85,12 +85,12 @@ public class DateTime {
                 || millisecond < FIELD_MINS[DateTime.MILLISECOND_FIELD_INDEX]) {
             return false;
         }
-        if ((timezoneHour > FIELD_MAXS[DateTime.HOUR_FIELD_INDEX] && timezoneHour != TIMEZONE_HOUR_NULL)
-                || (timezoneHour < FIELD_MINS[DateTime.HOUR_FIELD_INDEX] && timezoneHour != TIMEZONE_HOUR_NULL)) {
+        if ((timezoneHour > TIMEZONE_HOUR_MAX || timezoneHour < TIMEZONE_HOUR_MIN)
+                && (timezoneHour != TIMEZONE_HOUR_NULL)) {
             return false;
         }
-        if ((timezoneHour > FIELD_MAXS[DateTime.MINUTE_FIELD_INDEX] && timezoneHour != TIMEZONE_MINUTE_NULL)
-                || (timezoneHour < FIELD_MINS[DateTime.MINUTE_FIELD_INDEX] && timezoneHour != TIMEZONE_MINUTE_NULL)) {
+        if ((timezoneMinute > TIMEZONE_MINUTE_MAX || timezoneMinute < TIMEZONE_MINUTE_MIN)
+                && (timezoneMinute != TIMEZONE_MINUTE_NULL)) {
             return false;
         }
         return true;

Modified: incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDateTimeOperation.java
URL: http://svn.apache.org/viewvc/incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDateTimeOperation.java?rev=1368769&r1=1368768&r2=1368769&view=diff
==============================================================================
--- incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDateTimeOperation.java (original)
+++ incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToDateTimeOperation.java Fri Aug  3 02:12:26 2012
@@ -44,6 +44,7 @@ public class CastToDateTimeOperation ext
         long[] date = new long[8];
         boolean positiveTimezone = false;
         boolean pastDecimal = false;
+        boolean negativeYear = false;
         byte decimalPlace = 3;
 
         // Set defaults
@@ -52,37 +53,55 @@ public class CastToDateTimeOperation ext
 
         while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR) {
             if (Character.isDigit(c)) {
+                // Add the digit to the current numbered index.
                 date[index] = date[index] * 10 + Character.getNumericValue(c);
                 if (pastDecimal) {
                     --decimalPlace;
                 }
+            } else if (c == Character.valueOf('-') && index == 0 && date[index] == 0) {
+                // If the first dash does not have a number in front, its a negative year.
+                negativeYear = true;
             } else if (c == Character.valueOf('-') || c == Character.valueOf(':') || c == Character.valueOf('T')) {
+                // The basic case for going to the next number in the series.
                 ++index;
                 pastDecimal = false;
+                date[index] = 0;
             } else if (c == Character.valueOf('+')) {
+                // Moving to the next number and logging this is now a positive timezone offset.
+                ++index;
                 pastDecimal = false;
+                date[index] = 0;
                 positiveTimezone = true;
-                ++index;
             } else if (c == Character.valueOf('.')) {
+                // Only used by the seconds attribute.
                 pastDecimal = true;
+            } else if (c == Character.valueOf('Z')) {
+                // Set the timezone to UTC.
+                date[6] = 0;
+                date[7] = 0;
             } else {
                 // Invalid date format.
                 throw new SystemException(ErrorCode.FORG0001);
             }
         }
-        // Final touches on seconds and timezone.
+
+        // Final touches on year, seconds and timezone.
         date[5] = (long) (date[5] * Math.pow(10, decimalPlace));
+        if (negativeYear) {
+            date[0] *= -1;
+        }
         if (!positiveTimezone && date[6] != DateTime.TIMEZONE_HOUR_NULL) {
             date[6] *= -1;
         }
         if (!positiveTimezone && date[7] != DateTime.TIMEZONE_MINUTE_NULL) {
             date[7] *= -1;
         }
+
         // Double check for a valid datetime
         if (!DateTime.valid(date[0], date[1], date[2], date[3], date[4], date[5], date[6], date[7])) {
             throw new SystemException(ErrorCode.FODT0001);
         }
-        
+
         dOut.write(ValueTag.XS_DATETIME_TAG);
         dOut.writeShort((short) date[0]);
         dOut.write((byte) date[1]);

Modified: incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGDayOperation.java
URL: http://svn.apache.org/viewvc/incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGDayOperation.java?rev=1368769&r1=1368768&r2=1368769&view=diff
==============================================================================
--- incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGDayOperation.java (original)
+++ incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGDayOperation.java Fri Aug  3 02:12:26 2012
@@ -22,8 +22,8 @@ public class CastToGDayOperation extends
         dOut.writeShort((short) 1972);
         dOut.write((byte) 12);
         dOut.write((byte) datep.getDay());
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datep.getTimezoneHour());
+        dOut.write((byte) datep.getTimezoneMinute());
     }
 
     @Override
@@ -32,11 +32,8 @@ public class CastToGDayOperation extends
         dOut.writeShort((short) 1972);
         dOut.write((byte) 12);
         dOut.write((byte) datetimep.getDay());
-        dOut.write((byte) 0);
-        dOut.write((byte) 0);
-        dOut.writeInt((int) 0);
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datetimep.getTimezoneHour());
+        dOut.write((byte) datetimep.getTimezoneMinute());
     }
 
     @Override
@@ -60,12 +57,21 @@ public class CastToGDayOperation extends
 
         while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR) {
             if (Character.isDigit(c)) {
+                // Add the digit to the current numbered index.
                 date[index] = date[index] * 10 + Character.getNumericValue(c);
             } else if (c == Character.valueOf('-') || c == Character.valueOf(':')) {
+                // The basic case for going to the next number in the series.
                 ++index;
+                date[index] = 0;
             } else if (c == Character.valueOf('+')) {
-                positiveTimezone = true;
+                // Moving to the next number and logging this is now a positive timezone offset.
                 ++index;
+                date[index] = 0;
+                positiveTimezone = true;
+            } else if (c == Character.valueOf('Z')) {
+                // Set the timezone to UTC.
+                date[4] = 0;
+                date[5] = 0;
             } else {
                 // Invalid date format.
                 throw new SystemException(ErrorCode.FORG0001);

Modified: incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthDayOperation.java
URL: http://svn.apache.org/viewvc/incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthDayOperation.java?rev=1368769&r1=1368768&r2=1368769&view=diff
==============================================================================
--- incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthDayOperation.java (original)
+++ incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthDayOperation.java Fri Aug  3 02:12:26 2012
@@ -22,8 +22,8 @@ public class CastToGMonthDayOperation ex
         dOut.writeShort((short) 1972);
         dOut.write((byte) datep.getMonth());
         dOut.write((byte) datep.getDay());
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datep.getTimezoneHour());
+        dOut.write((byte) datep.getTimezoneMinute());
     }
 
     @Override
@@ -32,11 +32,8 @@ public class CastToGMonthDayOperation ex
         dOut.writeShort((short) 1972);
         dOut.write((byte) datetimep.getMonth());
         dOut.write((byte) datetimep.getDay());
-        dOut.write((byte) 0);
-        dOut.write((byte) 0);
-        dOut.writeInt((int) 0);
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datetimep.getTimezoneHour());
+        dOut.write((byte) datetimep.getTimezoneMinute());
     }
 
     @Override
@@ -60,12 +57,21 @@ public class CastToGMonthDayOperation ex
 
         while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR) {
             if (Character.isDigit(c)) {
+                // Add the digit to the current numbered index.
                 date[index] = date[index] * 10 + Character.getNumericValue(c);
             } else if (c == Character.valueOf('-') || c == Character.valueOf(':')) {
+                // The basic case for going to the next number in the series.
                 ++index;
+                date[index] = 0;
             } else if (c == Character.valueOf('+')) {
-                positiveTimezone = true;
+                // Moving to the next number and logging this is now a positive timezone offset.
                 ++index;
+                date[index] = 0;
+                positiveTimezone = true;
+            } else if (c == Character.valueOf('Z')) {
+                // Set the timezone to UTC.
+                date[4] = 0;
+                date[5] = 0;
             } else {
                 // Invalid date format.
                 throw new SystemException(ErrorCode.FORG0001);

Modified: incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthOperation.java
URL: http://svn.apache.org/viewvc/incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthOperation.java?rev=1368769&r1=1368768&r2=1368769&view=diff
==============================================================================
--- incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthOperation.java (original)
+++ incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGMonthOperation.java Fri Aug  3 02:12:26 2012
@@ -22,8 +22,8 @@ public class CastToGMonthOperation exten
         dOut.writeShort((short) 1972);
         dOut.write((byte) datep.getMonth());
         dOut.write((byte) 29);
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datep.getTimezoneHour());
+        dOut.write((byte) datep.getTimezoneMinute());
     }
 
     @Override
@@ -32,11 +32,8 @@ public class CastToGMonthOperation exten
         dOut.writeShort((short) 1972);
         dOut.write((byte) datetimep.getMonth());
         dOut.write((byte) 29);
-        dOut.write((byte) 0);
-        dOut.write((byte) 0);
-        dOut.writeInt((int) 0);
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datetimep.getTimezoneHour());
+        dOut.write((byte) datetimep.getTimezoneMinute());
     }
 
     @Override
@@ -51,43 +48,52 @@ public class CastToGMonthOperation exten
         charIterator.reset();
         int c;
         int index = 0;
-        long[] date = new long[3];
+        long[] date = new long[5];
         boolean positiveTimezone = false;
 
         // Set defaults
-        date[1] = DateTime.TIMEZONE_HOUR_NULL;
-        date[2] = DateTime.TIMEZONE_MINUTE_NULL;
+        date[3] = DateTime.TIMEZONE_HOUR_NULL;
+        date[4] = DateTime.TIMEZONE_MINUTE_NULL;
 
         while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR) {
             if (Character.isDigit(c)) {
+                // Add the digit to the current numbered index.
                 date[index] = date[index] * 10 + Character.getNumericValue(c);
             } else if (c == Character.valueOf('-') || c == Character.valueOf(':')) {
+                // The basic case for going to the next number in the series.
                 ++index;
+                date[index] = 0;
             } else if (c == Character.valueOf('+')) {
-                positiveTimezone = true;
+                // Moving to the next number and logging this is now a positive timezone offset.
                 ++index;
+                date[index] = 0;
+                positiveTimezone = true;
+            } else if (c == Character.valueOf('Z')) {
+                // Set the timezone to UTC.
+                date[3] = 0;
+                date[4] = 0;
             } else {
                 // Invalid date format.
                 throw new SystemException(ErrorCode.FORG0001);
             }
         }
         // Final touches on timezone.
-        if (!positiveTimezone && date[1] != DateTime.TIMEZONE_HOUR_NULL) {
-            date[1] *= -1;
+        if (!positiveTimezone && date[3] != DateTime.TIMEZONE_HOUR_NULL) {
+            date[3] *= -1;
         }
-        if (!positiveTimezone && date[2] != DateTime.TIMEZONE_MINUTE_NULL) {
-            date[2] *= -1;
+        if (!positiveTimezone && date[4] != DateTime.TIMEZONE_MINUTE_NULL) {
+            date[4] *= -1;
         }
-        if (!DateTime.valid(1972, date[0], 29, 0, 0, 0, date[1], date[2])) {
+        if (!DateTime.valid(1972, date[2], 29, 0, 0, 0, date[3], date[4])) {
             throw new SystemException(ErrorCode.FODT0001);
         }
 
         dOut.write(ValueTag.XS_G_MONTH_TAG);
         dOut.writeShort((short) 1972);
-        dOut.write((byte) date[0]);
-        dOut.write((byte) 29);
-        dOut.write((byte) date[1]);
         dOut.write((byte) date[2]);
+        dOut.write((byte) 29);
+        dOut.write((byte) date[3]);
+        dOut.write((byte) date[4]);
     }
 
     @Override

Modified: incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearMonthOperation.java
URL: http://svn.apache.org/viewvc/incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearMonthOperation.java?rev=1368769&r1=1368768&r2=1368769&view=diff
==============================================================================
--- incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearMonthOperation.java (original)
+++ incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearMonthOperation.java Fri Aug  3 02:12:26 2012
@@ -26,8 +26,8 @@ public class CastToGYearMonthOperation e
         } else {
             dOut.write((byte) DateTime.DAYS_OF_MONTH_LEAP[(int) (datep.getMonth() - 1)]);
         }
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datep.getTimezoneHour());
+        dOut.write((byte) datep.getTimezoneMinute());
     }
 
     @Override
@@ -40,11 +40,8 @@ public class CastToGYearMonthOperation e
         } else {
             dOut.write((byte) DateTime.DAYS_OF_MONTH_LEAP[(int) (datetimep.getMonth() - 1)]);
         }
-        dOut.write((byte) 0);
-        dOut.write((byte) 0);
-        dOut.writeInt((int) 0);
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datetimep.getTimezoneHour());
+        dOut.write((byte) datetimep.getTimezoneMinute());
     }
 
     @Override
@@ -61,6 +58,7 @@ public class CastToGYearMonthOperation e
         int index = 0;
         long[] date = new long[4];
         boolean positiveTimezone = false;
+        boolean negativeYear = false;
 
         // Set defaults
         date[2] = DateTime.TIMEZONE_HOUR_NULL;
@@ -68,18 +66,33 @@ public class CastToGYearMonthOperation e
 
         while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR) {
             if (Character.isDigit(c)) {
+                // Add the digit to the current numbered index.
                 date[index] = date[index] * 10 + Character.getNumericValue(c);
+            } else if (c == Character.valueOf('-') && index == 0 && date[index] == 0) {
+                // If the first dash does not have a number in front, its a negative year.
+                negativeYear = true;
             } else if (c == Character.valueOf('-') || c == Character.valueOf(':')) {
+                // The basic case for going to the next number in the series.
                 ++index;
+                date[index] = 0;
             } else if (c == Character.valueOf('+')) {
-                positiveTimezone = true;
+                // Moving to the next number and logging this is now a positive timezone offset.
                 ++index;
+                date[index] = 0;
+                positiveTimezone = true;
+            } else if (c == Character.valueOf('Z')) {
+                // Set the timezone to UTC.
+                date[2] = 0;
+                date[3] = 0;
             } else {
                 // Invalid date format.
                 throw new SystemException(ErrorCode.FORG0001);
             }
         }
-        // Final touches on timezone.
+        // Final touches on year and timezone.
+        if (negativeYear) {
+            date[0] *= -1;
+        }
         if (!positiveTimezone && date[2] != DateTime.TIMEZONE_HOUR_NULL) {
             date[2] *= -1;
         }

Modified: incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearOperation.java
URL: http://svn.apache.org/viewvc/incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearOperation.java?rev=1368769&r1=1368768&r2=1368769&view=diff
==============================================================================
--- incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearOperation.java (original)
+++ incubator/vxquery/trunk/vxquery/vxquery-core/src/main/java/org/apache/vxquery/runtime/functions/cast/CastToGYearOperation.java Fri Aug  3 02:12:26 2012
@@ -22,8 +22,8 @@ public class CastToGYearOperation extend
         dOut.writeShort((short) datep.getYear());
         dOut.write((byte) 1);
         dOut.write((byte) 1);
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datep.getTimezoneHour());
+        dOut.write((byte) datep.getTimezoneMinute());
     }
 
     @Override
@@ -32,11 +32,8 @@ public class CastToGYearOperation extend
         dOut.writeShort((short) datetimep.getYear());
         dOut.write((byte) 1);
         dOut.write((byte) 1);
-        dOut.write((byte) 0);
-        dOut.write((byte) 0);
-        dOut.writeInt((int) 0);
-        dOut.write((byte) DateTime.TIMEZONE_HOUR_NULL);
-        dOut.write((byte) DateTime.TIMEZONE_MINUTE_NULL);
+        dOut.write((byte) datetimep.getTimezoneHour());
+        dOut.write((byte) datetimep.getTimezoneMinute());
     }
 
     @Override
@@ -53,6 +50,7 @@ public class CastToGYearOperation extend
         int index = 0;
         long[] date = new long[3];
         boolean positiveTimezone = false;
+        boolean negativeYear = false;
 
         // Set defaults
         date[1] = DateTime.TIMEZONE_HOUR_NULL;
@@ -60,18 +58,33 @@ public class CastToGYearOperation extend
 
         while ((c = charIterator.next()) != ICharacterIterator.EOS_CHAR) {
             if (Character.isDigit(c)) {
+                // Add the digit to the current numbered index.
                 date[index] = date[index] * 10 + Character.getNumericValue(c);
+            } else if (c == Character.valueOf('-') && index == 0 && date[index] == 0) {
+                // If the first dash does not have a number in front, its a negative year.
+                negativeYear = true;
             } else if (c == Character.valueOf('-') || c == Character.valueOf(':')) {
+                // The basic case for going to the next number in the series.
                 ++index;
+                date[index] = 0;
             } else if (c == Character.valueOf('+')) {
-                positiveTimezone = true;
+                // Moving to the next number and logging this is now a positive timezone offset.
                 ++index;
+                date[index] = 0;
+                positiveTimezone = true;
+            } else if (c == Character.valueOf('Z')) {
+                // Set the timezone to UTC.
+                date[1] = 0;
+                date[2] = 0;
             } else {
                 // Invalid date format.
                 throw new SystemException(ErrorCode.FORG0001);
             }
         }
-        // Final touches on timezone.
+        // Final touches on year and timezone.
+        if (negativeYear) {
+            date[0] *= -1;
+        }
         if (!positiveTimezone && date[1] != DateTime.TIMEZONE_HOUR_NULL) {
             date[1] *= -1;
         }