Fix external issue 4110: DateTimeFormat rounds fractional seconds incorrectly

Review by: jlabanca



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7326 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/i18n/client/DateTimeFormat.java b/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
index 24122e8..e465dc3 100644
--- a/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
+++ b/user/src/com/google/gwt/i18n/client/DateTimeFormat.java
@@ -1003,9 +1003,15 @@
    * @param date hold the date object to be formatted
    */
   private void formatFractionalSeconds(StringBuffer buf, int count, Date date) {
-    // Fractional seconds should be left-justified, ie. zero must be padded
-    // from left. For example, if value in milliseconds is 5, and count is 3,
-    // the output need to be "005".
+    /*
+     * Fractional seconds should be left-justified, ie. zero must be padded from
+     * left. For example, if the value in milliseconds is 5, and the count is 3,
+     * the output will be "005".
+     * 
+     * Values with less than three digits are rounded to the desired number of
+     * places, but the rounded values are truncated at 9 or 99 in order to avoid
+     * changing the values of seconds.
+     */
     long time = date.getTime();
     int value;
     if (time < 0) {
@@ -1014,10 +1020,10 @@
       value = (int) (time % 1000);
     }
     if (count == 1) {
-      value = (value + 50) / 100; // Round to 100ms.
-      buf.append(Integer.toString(value));
+      value = Math.min((value + 50) / 100, 9); // Round to 100ms, clamp to 9
+      buf.append((char) ('0' + value));
     } else if (count == 2) {
-      value = (value + 5) / 10; // Round to 10ms.
+      value = Math.min((value + 5) / 10, 99); // Round to 10ms, clamp to 99
       zeroPaddingNumber(buf, value, 2);
     } else {
       zeroPaddingNumber(buf, value, 3);
@@ -1192,7 +1198,7 @@
       zeroPaddingNumber(buf, value % 100, 2);
     } else {
       // count != 2
-      buf.append(Integer.toString(value));
+      buf.append(value);
     }
   }
 
@@ -2044,6 +2050,6 @@
       }
       b *= NUMBER_BASE;
     }
-    buf.append(Integer.toString(value));
+    buf.append(value);
   }
 }
diff --git a/user/test/com/google/gwt/i18n/client/DateTimeFormat_en_Test.java b/user/test/com/google/gwt/i18n/client/DateTimeFormat_en_Test.java
index 2346aa8..332f7d9 100644
--- a/user/test/com/google/gwt/i18n/client/DateTimeFormat_en_Test.java
+++ b/user/test/com/google/gwt/i18n/client/DateTimeFormat_en_Test.java
@@ -122,6 +122,48 @@
     Date date = new Date(2006 - 1900, 6, 27, 13, 10, 10);
     assertEquals("J", DateTimeFormat.getFormat("LLLLL").format(date));
   }
+  
+  public void test_S() {
+    Date date = new Date(0);
+    assertEquals("0", DateTimeFormat.getFormat("S").format(date));
+    
+    date = new Date(55);
+    assertEquals("1", DateTimeFormat.getFormat("S").format(date));
+    
+    date = new Date(555);
+    assertEquals("6", DateTimeFormat.getFormat("S").format(date));
+    
+    date = new Date(999);
+    assertEquals("9", DateTimeFormat.getFormat("S").format(date));
+  }
+  
+  public void test_SS() {
+    Date date = new Date(0);
+    assertEquals("00", DateTimeFormat.getFormat("SS").format(date));
+    
+    date = new Date(55);
+    assertEquals("06", DateTimeFormat.getFormat("SS").format(date));
+    
+    date = new Date(555);
+    assertEquals("56", DateTimeFormat.getFormat("SS").format(date));
+    
+    date = new Date(999);
+    assertEquals("99", DateTimeFormat.getFormat("SS").format(date));
+  }
+  
+  public void test_SSS() {    
+    Date date = new Date(0);
+    assertEquals("000", DateTimeFormat.getFormat("SSS").format(date));
+    
+    date = new Date(55);
+    assertEquals("055", DateTimeFormat.getFormat("SSS").format(date));
+    
+    date = new Date(555);
+    assertEquals("555", DateTimeFormat.getFormat("SSS").format(date));
+    
+    date = new Date(999);
+    assertEquals("999", DateTimeFormat.getFormat("SSS").format(date));
+  }
 
   public void test_predefinedFormat() {
     Date date = new Date(2006 - 1900, 7, 4, 13, 49, 24);