You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2015/09/07 08:18:59 UTC

[7/8] olingo-odata4 git commit: [OLINGO-659] small improvement in DateTime serialization

[OLINGO-659] small improvement in DateTime serialization

Change-Id: Ieb0f00b5314be88bc0e38b74564538d1f4751c5b

Signed-off-by: Michael Bolz <mi...@sap.com>


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/72ad9b37
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/72ad9b37
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/72ad9b37

Branch: refs/heads/master
Commit: 72ad9b376bff518b5c28fe23eff6a8904b2b0c3f
Parents: 1277086
Author: Klaus Straubinger <kl...@sap.com>
Authored: Fri Sep 4 16:51:59 2015 +0200
Committer: Michael Bolz <mi...@sap.com>
Committed: Mon Sep 7 08:06:03 2015 +0200

----------------------------------------------------------------------
 .../edm/primitivetype/EdmDateTimeOffset.java    | 97 ++++++--------------
 .../core/edm/primitivetype/EdmTimeOfDay.java    |  6 +-
 .../primitivetype/EdmDateTimeOffsetTest.java    |  7 +-
 3 files changed, 37 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/72ad9b37/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
index ab295bf..61344fb 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffset.java
@@ -19,7 +19,6 @@
 package org.apache.olingo.commons.core.edm.primitivetype;
 
 import java.sql.Timestamp;
-import java.text.DecimalFormat;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
@@ -33,13 +32,6 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
  */
 public final class EdmDateTimeOffset extends SingletonPrimitiveType {
 
-  public static final ThreadLocal<DecimalFormat> NANO_FORMAT = new ThreadLocal<DecimalFormat>() {
-    @Override
-    protected DecimalFormat initialValue() {
-      return new DecimalFormat("000000000");
-    }
-  };
-
   private static final Pattern PATTERN = Pattern.compile(
       "(-?\\p{Digit}{4,})-(\\p{Digit}{2})-(\\p{Digit}{2})"
           + "T(\\p{Digit}{2}):(\\p{Digit}{2})(?::(\\p{Digit}{2})(\\.(\\p{Digit}{0,12}?)0*)?)?"
@@ -93,14 +85,15 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
       }
       if (returnType.isAssignableFrom(Timestamp.class)) {
         if (!decimals.isEmpty()) {
-          nanoSeconds = Integer.parseInt(decimals.length() > 9 ? decimals.substring(0, 9)
-              : decimals + "000000000".substring(decimals.length()));
+          nanoSeconds = Integer.parseInt(decimals.length() > 9 ?
+              decimals.substring(0, 9) :
+              decimals + "000000000".substring(decimals.length()));
         }
       } else {
-        final String milliSeconds = decimals.length() > 3
-            ? decimals.substring(0, 3)
-            : decimals + "000".substring(decimals.length());
-            dateTimeValue.set(Calendar.MILLISECOND, Short.parseShort(milliSeconds));
+        final String milliSeconds = decimals.length() > 3 ?
+            decimals.substring(0, 3) :
+            decimals + "000".substring(decimals.length());
+        dateTimeValue.set(Calendar.MILLISECOND, Short.parseShort(milliSeconds));
       }
     }
 
@@ -157,19 +150,16 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
       final Boolean isNullable, final Integer maxLength, final Integer precision,
       final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {
 
-    final Calendar dateTimeValue;
-    final int fractionalSecs;
+    Calendar dateTimeValue;
     if (value instanceof Timestamp) {
       final Calendar tmp = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
       tmp.setTimeInMillis(((Timestamp) value).getTime());
       dateTimeValue = createDateTime(tmp);
-      fractionalSecs = ((Timestamp) value).getNanos();
     } else {
       dateTimeValue = createDateTime(value);
-      fractionalSecs = dateTimeValue.get(Calendar.MILLISECOND);
     }
 
-    final StringBuilder result = new StringBuilder();
+    StringBuilder result = new StringBuilder();
     final int year = dateTimeValue.get(Calendar.YEAR);
     appendTwoDigits(result, year / 100);
     appendTwoDigits(result, year % 100);
@@ -184,12 +174,11 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
     result.append(':');
     appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
 
+    final int fractionalSecs = value instanceof Timestamp ?
+        ((Timestamp) value).getNanos() :
+        dateTimeValue.get(Calendar.MILLISECOND);
     try {
-      if (value instanceof Timestamp) {
-        appendFractionalSeconds(result, fractionalSecs, precision);
-      } else {
-        appendMilliseconds(result, fractionalSecs, precision);
-      }
+      appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
     } catch (final IllegalArgumentException e) {
       throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
     }
@@ -243,61 +232,35 @@ public final class EdmDateTimeOffset extends SingletonPrimitiveType {
   }
 
   /**
-   * Appends the given number of milliseconds to the given string builder, assuming that the number has at most three
-   * digits, performance-optimized.
-   *
+   * Appends the given milli- or nanoseconds to the given string builder, performance-optimized.
    * @param result a {@link StringBuilder}
-   * @param milliseconds an integer that must satisfy <code>0 &lt;= milliseconds &lt;= 999</code>
+   * @param fractionalSeconds fractional seconds (nonnegative and assumed to be in the valid range)
+   * @param isNano whether the value is to be interpreted as nanoseconds (milliseconds if false)
    * @param precision the upper limit for decimal digits (optional, defaults to zero)
    * @throws IllegalArgumentException if precision is not met
    */
-  protected static void appendMilliseconds(final StringBuilder result, final int milliseconds,
-      final Integer precision) throws IllegalArgumentException {
+  protected static void appendFractionalSeconds(StringBuilder result, final int fractionalSeconds,
+      final boolean isNano, final Integer precision) throws IllegalArgumentException {
+    if (fractionalSeconds > 0) {
+      // Determine the number of trailing zeroes.
+      int nonSignificant = 0;
+      int output = fractionalSeconds;
+      while (output % 10 == 0) {
+        output /= 10;
+        nonSignificant++;
+      }
 
-    final int digits = milliseconds % 1000 == 0 ? 0 : milliseconds % 100 == 0 ? 1 : milliseconds % 10 == 0 ? 2 : 3;
-    if (digits > 0) {
-      if (precision == null || precision < digits) {
+      if (precision == null || precision < (isNano ? 9 : 3) - nonSignificant) {
         throw new IllegalArgumentException();
       }
 
       result.append('.');
-      for (int d = 100; d > 0; d /= 10) {
-        final byte digit = (byte) (milliseconds % (d * 10) / d);
-        if (digit > 0 || milliseconds % d > 0) {
+      for (int d = 100 * (isNano ? 1000 * 1000 : 1); d > 0; d /= 10) {
+        final byte digit = (byte) (fractionalSeconds % (d * 10) / d);
+        if (digit > 0 || fractionalSeconds % d > 0) {
           result.append((char) ('0' + digit));
         }
       }
     }
   }
-
-  /**
-   * Appends the given fractional seconds to the given string builder.
-   *
-   * @param result a {@link StringBuilder}
-   * @param fractionalSeconds fractional seconds
-   * @param precision the upper limit for decimal digits (optional, defaults to zero)
-   * @throws IllegalArgumentException if precision is not met
-   */
-  protected static void appendFractionalSeconds(final StringBuilder result, final int fractionalSeconds,
-      final Integer precision) throws IllegalArgumentException {
-
-    if (fractionalSeconds > 0) {
-      String formatted = NANO_FORMAT.get().format(fractionalSeconds);
-      int actualLength = formatted.length();
-      boolean nonZeroFound = false;
-      for (int i = formatted.length() - 1; i >= 0 && !nonZeroFound; i--) {
-        if ('0' == formatted.charAt(i)) {
-          actualLength--;
-        } else {
-          nonZeroFound = true;
-        }
-      }
-
-      if (precision == null || precision < actualLength) {
-        throw new IllegalArgumentException();
-      }
-
-      result.append('.').append(formatted.substring(0, actualLength));
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/72ad9b37/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
index 7330fac..7595e51 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/primitivetype/EdmTimeOfDay.java
@@ -112,11 +112,7 @@ public final class EdmTimeOfDay extends SingletonPrimitiveType {
     EdmDateTimeOffset.appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
 
     try {
-      if (value instanceof Timestamp) {
-        EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, precision);
-      } else {
-        EdmDateTimeOffset.appendMilliseconds(result, fractionalSecs, precision);
-      }
+      EdmDateTimeOffset.appendFractionalSeconds(result, fractionalSecs, value instanceof Timestamp, precision);
     } catch (final IllegalArgumentException e) {
       throw new EdmPrimitiveTypeException("The value '" + value + "' does not match the facets' constraints.", e);
     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/72ad9b37/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
index d8ea7c9..17ea5ce 100644
--- a/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
+++ b/lib/commons-core/src/test/java/org/apache/olingo/commons/core/edm/primitivetype/EdmDateTimeOffsetTest.java
@@ -80,8 +80,13 @@ public class EdmDateTimeOffsetTest extends PrimitiveTypeBaseTest {
     final String time = date.toString().substring(11, 19);
     assertTrue(instance.valueToString(date, null, null, 3, null, null).contains(time));
 
+    Timestamp timestamp = new Timestamp(0);
+    timestamp.setNanos(120);
+    assertEquals("1970-01-01T00:00:00.00000012Z", instance.valueToString(timestamp, null, null, 8, null, null));
+
     expectFacetsErrorInValueToString(instance, millis, null, null, null, null, null);
     expectFacetsErrorInValueToString(instance, 3L, null, null, 2, null, null);
+    expectFacetsErrorInValueToString(instance, timestamp, null, null, 7, null, null);
 
     expectTypeErrorInValueToString(instance, 0);
   }
@@ -114,7 +119,7 @@ public class EdmDateTimeOffsetTest extends PrimitiveTypeBaseTest {
     dateTime.add(Calendar.MILLISECOND, 7);
     assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03.007+11:00", null, null, 3, null, null,
         Calendar.class));
-    assertEquals(530000000, instance.valueOfString("2012-02-29T01:02:03.53+11:00", null, null, 9, null, null,
+    assertEquals(530000001, instance.valueOfString("2012-02-29T01:02:03.530000001+11:00", null, null, 9, null, null,
         Timestamp.class).getNanos());
 
     assertEquals(Long.valueOf(120000L), instance.valueOfString("1970-01-01T00:02", null, null, null, null, null,