You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlbeans.apache.org by ce...@apache.org on 2009/06/10 23:05:24 UTC

svn commit: r783519 - in /xmlbeans/trunk: src/xmlpublic/org/apache/xmlbeans/GDate.java src/xmlpublic/org/apache/xmlbeans/GDateBuilder.java test/src/xmlobject/schematypes/checkin/GDateTests.java

Author: cezar
Date: Wed Jun 10 21:05:24 2009
New Revision: 783519

URL: http://svn.apache.org/viewvc?rev=783519&view=rev
Log:
Fix normalization of dates with hour 24.
Extended the year limitations or dates.
Added date tests


Modified:
    xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDate.java
    xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDateBuilder.java
    xmlbeans/trunk/test/src/xmlobject/schematypes/checkin/GDateTests.java

Modified: xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDate.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDate.java?rev=783519&r1=783518&r2=783519&view=diff
==============================================================================
--- xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDate.java (original)
+++ xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDate.java Wed Jun 10 21:05:24 2009
@@ -40,7 +40,12 @@
 public final class GDate implements GDateSpecification, java.io.Serializable
 {
     private static final long serialVersionUID = 1L;
-    
+
+    // XMLSchema spec requires support only for years 1 to 9999, but XMLBeans covers more up to the following limitations
+    // to avoid losing precision when transforming to a java.util.Date
+    static final int MAX_YEAR =  292277265;  // is Long.MAX_VALUE ms in years - 1 (for the 11month, 31days, 23h, 59m, 59sec case).
+    static final int MIN_YEAR = -292275295; // is Long.MIN_VALUE ms in years + 1970 + 1
+
     // for fast equality comparison, hashing, and serialization
     private transient String _canonicalString;
     private transient String _string;
@@ -143,8 +148,8 @@
                 start += 1;
             }
             digits += start;
-            if (digits > 6)
-                throw new IllegalArgumentException("year too long (up to 6 digits)");
+            if (digits > 9)
+                throw new IllegalArgumentException("year too long (up to 9 digits)");
             else if (digits >= 4)
             {
                 _bits |= HAS_YEAR;
@@ -154,6 +159,12 @@
             else if (digits > 0)
                 throw new IllegalArgumentException("year must be four digits (may pad with zeroes, e.g., 0560)");
 
+            /*if ( _CY > MAX_YEAR )
+                throw new IllegalArgumentException("year must be less than " + MAX_YEAR);
+
+            if ( _CY < MIN_YEAR )
+                throw new IllegalArgumentException("year must be bigger than " + MIN_YEAR);
+            */
             // hyphen introduces a month
             if (ch != '-')
             {
@@ -279,8 +290,7 @@
                 if ( hasDate() )
                 {
                     GDateBuilder gdb = new GDateBuilder(_CY, _M, _D, _h, _m, _s, _fs, _tzsign, _tzh, _tzm);
-                    gdb.normalize();
-                    gdb.normalizeToTimeZone(_tzsign, _tzh, _tzm);
+                    gdb.normalize24h();                    
 
                     _D = gdb.getDay();
                     _M = gdb.getMonth();

Modified: xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDateBuilder.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDateBuilder.java?rev=783519&r1=783518&r2=783519&view=diff
==============================================================================
--- xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDateBuilder.java (original)
+++ xmlbeans/trunk/src/xmlpublic/org/apache/xmlbeans/GDateBuilder.java Wed Jun 10 21:05:24 2009
@@ -374,13 +374,15 @@
     public final int getTimeZoneMinute()
         { return _tzm; }
 
+    
+
     /**
      * Sets the year. Should be a four-digit year specification.
      * @param year the year
      */
     public void setYear(int year)
     {
-        if (year < -4713 || year > 999999)
+        if (year < GDate.MIN_YEAR || year > GDate.MAX_YEAR)
             throw new IllegalArgumentException("year out of range");
         if (year == 0)
             throw new IllegalArgumentException("year cannot be 0");
@@ -602,37 +604,14 @@
         // DateTime or Time, with TimeZone: normalize to UTC.
         // In the process all the fields will be normalized.
         if (hasDay() == hasMonth() && hasDay() == hasYear() &&
-            hasTimeZone() && hasTime() && getHour()!=24 )
+            hasTimeZone() && hasTime() )
         {
             normalizeToTimeZone(0, 0, 0);
         }
         else
         {
             // No timezone, or incomplete date.
-            long carry = 0;
-
-            if (hasTime())
-                carry = _normalizeTime();
-
-            if (hasDay())
-                _D += carry;
-
-            if (hasDate())
-            {
-                _normalizeDate();
-            }
-            else if (hasMonth())
-            {
-                // with incomplete dates, just months can be normalized:
-                // days stay denormalized.
-                if (_M < 1 || _M > 12)
-                {
-                    int temp = _M;
-                    _M = _modulo(temp, 1, 13);
-                    if (hasYear())
-                        _CY = _CY + (int)_fQuotient(temp, 1, 13);
-                }
-            }
+            _normalizeTimeAndDate();
         }
 
         // remove trailing zeros from fractional seconds
@@ -654,6 +633,46 @@
         }
     }
 
+   /**
+     * Normalizes the instance when hour is 24. If day is present, hour 24 is equivalent to hour 00 next day.
+     */
+    void normalize24h()
+    {
+        if ( !hasTime() || getHour()!=24 )
+            return;
+
+        _normalizeTimeAndDate();
+    }
+
+
+    private void _normalizeTimeAndDate()
+    {
+        long carry = 0;
+
+        if (hasTime())
+            carry = _normalizeTime();
+
+        if (hasDay())
+            _D += carry;
+
+        if (hasDate())
+        {
+            _normalizeDate();
+        }
+        else if (hasMonth())
+        {
+            // with incomplete dates, just months can be normalized:
+            // days stay denormalized.
+            if (_M < 1 || _M > 12)
+            {
+                int temp = _M;
+                _M = _modulo(temp, 1, 13);
+                if (hasYear())
+                    _CY = _CY + (int)_fQuotient(temp, 1, 13);
+            }
+        }
+    }
+
     /**
      * If the time and timezone are known, this method changes the timezone to the
      * specified UTC offset, altering minutes, hours, day, month, and year as

Modified: xmlbeans/trunk/test/src/xmlobject/schematypes/checkin/GDateTests.java
URL: http://svn.apache.org/viewvc/xmlbeans/trunk/test/src/xmlobject/schematypes/checkin/GDateTests.java?rev=783519&r1=783518&r2=783519&view=diff
==============================================================================
--- xmlbeans/trunk/test/src/xmlobject/schematypes/checkin/GDateTests.java (original)
+++ xmlbeans/trunk/test/src/xmlobject/schematypes/checkin/GDateTests.java Wed Jun 10 21:05:24 2009
@@ -29,6 +29,7 @@
 import java.util.GregorianCalendar;
 import java.util.Date;
 import java.util.Calendar;
+import java.math.BigDecimal;
 
 public class GDateTests extends TestCase
 {
@@ -134,8 +135,8 @@
                 "00:00", // time incomplete
                 "00", // incomplete
                 "2100-02-29", // not leap
-                "-9999999-02-28T00:00:00Z", // too long ago
-                "9999999-02-28T00:00:00Z", // too long from now
+                "-999999999-02-28T00:00:00Z", // too long ago
+                "999999999-02-28T00:00:00Z", // too long from now
                 "9999999999999999999999999999999-02-28T00:00:00Z", // overflow?
                 "0000-01-01", // year zero
                 "0000-12-31T04:35:22.456", // year zero
@@ -635,4 +636,89 @@
             }
         }
     }
+
+    public void test24hDates()
+    {
+        GDate d1 = new GDate("2004-03-31T24:00:00");
+        Assert.assertEquals("2004-04-01T00:00:00", d1.toString());
+
+
+        GDateBuilder b = new GDateBuilder();
+        b.setTime(24, 0, 0, new BigDecimal("0.00"));
+        System.out.println("hour 24: " + b.getCalendar());
+        Assert.assertEquals("24:00:00.000", b.getCalendar().toString());
+
+        b.setDay(10);
+        b.setMonth(1);
+        System.out.println("hour 24: " + b.getCalendar());
+        Assert.assertEquals("--01-10T24:00:00.000", b.getCalendar().toString());
+
+        b.setYear(2010);
+        System.out.println("hour 24: " + b.getCalendar());
+        Assert.assertEquals("2010-01-10T24:00:00.000", b.getCalendar().toString());
+
+        b.setDay(31);
+        b.setMonth(03);
+        b.setYear(2004);
+
+        System.out.println("hour 24: canonical str: " + b.canonicalString());
+        Assert.assertEquals("2004-04-01T00:00:00", b.canonicalString());
+        System.out.println("hour 24: toString: " + b.toString());
+        Assert.assertEquals("2004-03-31T24:00:00.00", b.toString());
+        System.out.println("hour 24: toGDate: " + b.toGDate());
+        Assert.assertEquals("2004-03-31T24:00:00.00", b.toGDate().toString());
+        System.out.println("hour 24: toGDate().canonicalStr: " + b.toGDate().canonicalString());
+        Assert.assertEquals("2004-04-01T00:00:00", b.toGDate().canonicalString());
+        System.out.println("hour 24: toGDate().getCal: " + b.toGDate().getCalendar());
+        Assert.assertEquals("2004-03-31T24:00:00.000", b.toGDate().getCalendar().toString());
+
+
+        GDateBuilder gdb = new GDateBuilder("24:00:00+01:00");
+        System.out.println("gdb: " + gdb);
+        Assert.assertEquals("24:00:00+01:00", gdb.toString());
+
+        gdb.normalize();
+        System.out.println("gdb.normalize(): " + gdb);
+        Assert.assertEquals("23:00:00Z", gdb.toString());
+    }
+
+    public void testYearStartingWith0()
+    {
+        GDate gdate = new GDate("0004-08-01");    //      00004-08-01 must fail
+        System.out.println("year starting with 0: " + gdate.getCalendar());
+        Assert.assertEquals("0004-08-01", gdate.toString());
+
+        String txt = "-9999-06";
+        GDate d = new GDate(txt);
+        System.out.println(" gdate(" + txt + ") = " + d);
+        Assert.assertEquals("-9999-06", d.toString());
+
+        txt = "-12345-06";
+        d = new GDate(txt);
+        System.out.println(" gdate(" + txt + ") = " + d);
+        Assert.assertEquals(txt, d.toString());
+
+
+        try
+        {
+            txt = "00004-08-01";
+            d = new GDate(txt);    //      00004-08-01 must fail
+            Assert.assertTrue("Year starting with 0 of five digits: " + txt, false);
+        }
+        catch(IllegalArgumentException e)
+        {
+            Assert.assertTrue("Year starting with 0 of five digits: " + txt, true);
+        }
+
+        try
+        {
+            txt = "-012340-08-01";
+            d = new GDate(txt);
+            Assert.assertTrue("Year starting with 0 of six digits: " + txt, false);
+        }
+        catch(IllegalArgumentException e)
+        {
+            Assert.assertTrue("Year starting with 0 of six digits: " + txt, true);
+        }
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: commits-help@xmlbeans.apache.org