You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2014/05/21 17:54:40 UTC
[3/5] git commit: Add missing iso8601 patterns for date strings
Add missing iso8601 patterns for date strings
patch by chander; reviewed by slebresne for CASSANDRA-6973
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/26356322
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/26356322
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/26356322
Branch: refs/heads/trunk
Commit: 2635632270289fbbab2f3e3181f20aa98c34a879
Parents: 484d281
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Wed May 21 17:29:12 2014 +0200
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Wed May 21 17:29:12 2014 +0200
----------------------------------------------------------------------
CHANGES.txt | 4 +
.../apache/cassandra/db/marshal/DateType.java | 41 +----------
.../cassandra/db/marshal/TimeUUIDType.java | 6 +-
.../cassandra/db/marshal/TimestampType.java | 43 +----------
.../apache/cassandra/db/marshal/UUIDType.java | 38 ++--------
.../serializers/TimestampSerializer.java | 68 ++++++++++++++---
.../serializers/TimestampSerializerTest.java | 77 ++++++++++++++++++++
7 files changed, 152 insertions(+), 125 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26356322/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 3f8e3d0..bddb1d1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,7 @@
+2.0.9
+ * Add missing iso8601 patterns for date strings (6973)
+
+
2.0.8
* Always reallocate buffers in HSHA (CASSANDRA-6285)
* (Hadoop) support authentication in CqlRecordReader (CASSANDRA-7221)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26356322/src/java/org/apache/cassandra/db/marshal/DateType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/DateType.java b/src/java/org/apache/cassandra/db/marshal/DateType.java
index 8e28bd4..0c97688 100644
--- a/src/java/org/apache/cassandra/db/marshal/DateType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DateType.java
@@ -38,9 +38,6 @@ public class DateType extends AbstractType<Date>
public static final DateType instance = new DateType();
- static final String DEFAULT_FORMAT = TimestampSerializer.iso8601Patterns[3];
- static final SimpleDateFormat FORMATTER = new SimpleDateFormat(DEFAULT_FORMAT);
-
DateType() {} // singleton
public int compare(ByteBuffer o1, ByteBuffer o2)
@@ -63,43 +60,7 @@ public class DateType extends AbstractType<Date>
if (source.isEmpty())
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
- return ByteBufferUtil.bytes(dateStringToTimestamp(source));
- }
-
- public static long dateStringToTimestamp(String source) throws MarshalException
- {
- long millis;
-
- if (source.toLowerCase().equals("now"))
- {
- millis = System.currentTimeMillis();
- }
- // Milliseconds since epoch?
- else if (source.matches("^-?\\d+$"))
- {
- try
- {
- millis = Long.parseLong(source);
- }
- catch (NumberFormatException e)
- {
- throw new MarshalException(String.format("unable to make long (for date) from: '%s'", source), e);
- }
- }
- // Last chance, attempt to parse as date-time string
- else
- {
- try
- {
- millis = DateUtils.parseDateStrictly(source, TimestampSerializer.iso8601Patterns).getTime();
- }
- catch (ParseException e1)
- {
- throw new MarshalException(String.format("unable to coerce '%s' to a formatted date (long)", source), e1);
- }
- }
-
- return millis;
+ return ByteBufferUtil.bytes(TimestampSerializer.dateStringToTimestamp(source));
}
@Override
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26356322/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java b/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
index 51cf47a..fa82f06 100644
--- a/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
@@ -25,6 +25,7 @@ import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.serializers.TimeUUIDSerializer;
+import org.apache.cassandra.serializers.TimestampSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.UUIDGen;
@@ -110,9 +111,10 @@ public class TimeUUIDType extends AbstractType<UUID>
if (uuid.version() != 1)
throw new MarshalException("TimeUUID supports only version 1 UUIDs");
- } else
+ }
+ else
{
- idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(DateType.dateStringToTimestamp(source)));
+ idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(TimestampSerializer.dateStringToTimestamp(source)));
}
return idBytes;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26356322/src/java/org/apache/cassandra/db/marshal/TimestampType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/TimestampType.java b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
index cf1ea41..69ead8e 100644
--- a/src/java/org/apache/cassandra/db/marshal/TimestampType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
@@ -18,9 +18,7 @@
package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
-import java.text.ParseException;
import java.util.Date;
-import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,7 +27,6 @@ import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.serializers.TimestampSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
-import org.apache.commons.lang3.time.DateUtils;
/**
* Type for date-time values.
@@ -44,8 +41,6 @@ public class TimestampType extends AbstractType<Date>
public static final TimestampType instance = new TimestampType();
- private static final Pattern timestampPattern = Pattern.compile("^-?\\d+$");
-
private TimestampType() {} // singleton
public int compare(ByteBuffer o1, ByteBuffer o2)
@@ -59,43 +54,7 @@ public class TimestampType extends AbstractType<Date>
if (source.isEmpty())
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
- return ByteBufferUtil.bytes(dateStringToTimestamp(source));
- }
-
- public static long dateStringToTimestamp(String source) throws MarshalException
- {
- long millis;
-
- if (source.toLowerCase().equals("now"))
- {
- millis = System.currentTimeMillis();
- }
- // Milliseconds since epoch?
- else if (timestampPattern.matcher(source).matches())
- {
- try
- {
- millis = Long.parseLong(source);
- }
- catch (NumberFormatException e)
- {
- throw new MarshalException(String.format("unable to make long (for date) from: '%s'", source), e);
- }
- }
- // Last chance, attempt to parse as date-time string
- else
- {
- try
- {
- millis = DateUtils.parseDateStrictly(source, TimestampSerializer.iso8601Patterns).getTime();
- }
- catch (ParseException e1)
- {
- throw new MarshalException(String.format("unable to coerce '%s' to a formatted date (long)", source), e1);
- }
- }
-
- return millis;
+ return ByteBufferUtil.bytes(TimestampSerializer.dateStringToTimestamp(source));
}
@Override
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26356322/src/java/org/apache/cassandra/db/marshal/UUIDType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/UUIDType.java b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
index 4b0751e..969ff17 100644
--- a/src/java/org/apache/cassandra/db/marshal/UUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
@@ -26,12 +26,11 @@ import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.serializers.UUIDSerializer;
+import org.apache.cassandra.serializers.TimestampSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.UUIDGen;
import org.apache.commons.lang3.time.DateUtils;
-import static org.apache.cassandra.serializers.TimestampSerializer.iso8601Patterns;
-
/**
* Compares UUIDs using the following criteria:<br>
* - if count of supplied bytes is less than 16, compare counts<br>
@@ -165,8 +164,6 @@ public class UUIDType extends AbstractType<UUID>
if (source.isEmpty())
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
- ByteBuffer idBytes = null;
-
// ffffffff-ffff-ffff-ffff-ffffffffff
if (TimeUUIDType.regexPattern.matcher(source).matches())
{
@@ -174,43 +171,22 @@ public class UUIDType extends AbstractType<UUID>
try
{
uuid = UUID.fromString(source);
- idBytes = ByteBuffer.wrap(UUIDGen.decompose(uuid));
+ return ByteBuffer.wrap(UUIDGen.decompose(uuid));
}
catch (IllegalArgumentException e)
{
throw new MarshalException(String.format("unable to make UUID from '%s'", source), e);
}
- } else if (source.toLowerCase().equals("now"))
- {
- idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
}
- // Milliseconds since epoch?
- else if (source.matches("^\\d+$"))
+
+ try
{
- try
- {
- idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(Long.parseLong(source)));
- }
- catch (NumberFormatException e)
- {
- throw new MarshalException(String.format("unable to make version 1 UUID from '%s'", source), e);
- }
+ return ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(TimestampSerializer.dateStringToTimestamp(source)));
}
- // Last chance, attempt to parse as date-time string
- else
+ catch (MarshalException e)
{
- try
- {
- long timestamp = DateUtils.parseDate(source, iso8601Patterns).getTime();
- idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(timestamp));
- }
- catch (ParseException e1)
- {
- throw new MarshalException(String.format("unable to coerce '%s' to version 1 UUID", source), e1);
- }
+ throw new MarshalException(String.format("unable to make version 1 UUID from '%s'", source), e);
}
-
- return idBytes;
}
public CQL3Type asCQL3Type()
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26356322/src/java/org/apache/cassandra/serializers/TimestampSerializer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/serializers/TimestampSerializer.java b/src/java/org/apache/cassandra/serializers/TimestampSerializer.java
index f2a40f1..5cb9586 100644
--- a/src/java/org/apache/cassandra/serializers/TimestampSerializer.java
+++ b/src/java/org/apache/cassandra/serializers/TimestampSerializer.java
@@ -21,30 +21,49 @@ import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
+import java.text.ParseException;
import java.util.Date;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.time.DateUtils;
public class TimestampSerializer implements TypeSerializer<Date>
{
- public static final String[] iso8601Patterns = new String[] {
+ private static final String[] dateStringPatterns = new String[] {
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd HH:mm:ss",
- "yyyy-MM-dd HH:mmZ",
- "yyyy-MM-dd HH:mm:ssZ",
+ "yyyy-MM-dd HH:mmX",
+ "yyyy-MM-dd HH:mmXX",
+ "yyyy-MM-dd HH:mmXXX",
+ "yyyy-MM-dd HH:mm:ssX",
+ "yyyy-MM-dd HH:mm:ssXX",
+ "yyyy-MM-dd HH:mm:ssXXX",
"yyyy-MM-dd HH:mm:ss.SSS",
- "yyyy-MM-dd HH:mm:ss.SSSZ",
+ "yyyy-MM-dd HH:mm:ss.SSSX",
+ "yyyy-MM-dd HH:mm:ss.SSSXX",
+ "yyyy-MM-dd HH:mm:ss.SSSXXX",
"yyyy-MM-dd'T'HH:mm",
- "yyyy-MM-dd'T'HH:mmZ",
+ "yyyy-MM-dd'T'HH:mmX",
+ "yyyy-MM-dd'T'HH:mmXX",
+ "yyyy-MM-dd'T'HH:mmXXX",
"yyyy-MM-dd'T'HH:mm:ss",
- "yyyy-MM-dd'T'HH:mm:ssZ",
+ "yyyy-MM-dd'T'HH:mm:ssX",
+ "yyyy-MM-dd'T'HH:mm:ssXX",
+ "yyyy-MM-dd'T'HH:mm:ssXXX",
"yyyy-MM-dd'T'HH:mm:ss.SSS",
- "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
+ "yyyy-MM-dd'T'HH:mm:ss.SSSX",
+ "yyyy-MM-dd'T'HH:mm:ss.SSSXX",
+ "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
"yyyy-MM-dd",
- "yyyy-MM-ddZ"
+ "yyyy-MM-ddX",
+ "yyyy-MM-ddXX",
+ "yyyy-MM-ddXXX"
};
- static final String DEFAULT_FORMAT = iso8601Patterns[3];
+ private static final String DEFAULT_FORMAT = dateStringPatterns[3];
+ private static final Pattern timestampPattern = Pattern.compile("^-?\\d+$");
- static final ThreadLocal<SimpleDateFormat> FORMATTER = new ThreadLocal<SimpleDateFormat>()
+ private static final ThreadLocal<SimpleDateFormat> FORMATTER = new ThreadLocal<SimpleDateFormat>()
{
protected SimpleDateFormat initialValue()
{
@@ -64,6 +83,35 @@ public class TimestampSerializer implements TypeSerializer<Date>
return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value.getTime());
}
+ public static long dateStringToTimestamp(String source) throws MarshalException
+ {
+ if (source.equalsIgnoreCase("now"))
+ return System.currentTimeMillis();
+
+ // Milliseconds since epoch?
+ if (timestampPattern.matcher(source).matches())
+ {
+ try
+ {
+ return Long.parseLong(source);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new MarshalException(String.format("unable to make long (for date) from: '%s'", source), e);
+ }
+ }
+
+ // Last chance, attempt to parse as date-time string
+ try
+ {
+ return DateUtils.parseDateStrictly(source, dateStringPatterns).getTime();
+ }
+ catch (ParseException e1)
+ {
+ throw new MarshalException(String.format("unable to coerce '%s' to a formatted date (long)", source), e1);
+ }
+ }
+
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 8 && bytes.remaining() != 0)
http://git-wip-us.apache.org/repos/asf/cassandra/blob/26356322/test/unit/org/apache/cassandra/serializers/TimestampSerializerTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/serializers/TimestampSerializerTest.java b/test/unit/org/apache/cassandra/serializers/TimestampSerializerTest.java
new file mode 100644
index 0000000..d991845
--- /dev/null
+++ b/test/unit/org/apache/cassandra/serializers/TimestampSerializerTest.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cassandra.serializers;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.cassandra.serializers.MarshalException;
+import org.apache.cassandra.serializers.TimestampSerializer;
+
+public class TimestampSerializerTest
+{
+ private String dates[] = new String[]
+ {
+ "2014-04-01",
+ "2014-04-01+0000",
+ "2014-04-01 20:30",
+ "2014-04-01 20:30:35",
+ "2014-04-01 20:30:35Z",
+ "2014-04-01 20:30+07",
+ "2014-04-01 20:30+0700",
+ "2014-04-01 20:30+07:00",
+ "2014-04-01 20:30:35+07",
+ "2014-04-01 20:30:35+0700",
+ "2014-04-01 20:30:35+07:00",
+ "2014-04-01 20:30:35.898",
+ "2014-04-01 20:30:35.898Z",
+ "2014-04-01 20:30:35.898+07",
+ "2014-04-01 20:30:35.898+0700",
+ "2014-04-01 20:30:35.898+07:00",
+ "2014-04-01T20:30",
+ "2014-04-01T20:30:25",
+ "2014-04-01T20:30:35Z",
+ "2014-04-01T20:30:35+00:00",
+ "2014-04-01T20:30:35+0700",
+ "2014-04-01T20:30:35+07:00",
+ "2014-04-01T20:30:35.898",
+ "2014-04-01T20:30:35.898+00:00"
+ };
+
+ @Test
+ public void testDateStringToTimestamp()
+ {
+ List<String> unparsedDates = new ArrayList<>();
+ for (String date: dates)
+ {
+ try
+ {
+ long millis = TimestampSerializer.dateStringToTimestamp(date);
+ }
+ catch (MarshalException e)
+ {
+ unparsedDates.add(date);
+ }
+ }
+ assertTrue("Unable to parse: " + unparsedDates, unparsedDates.isEmpty());
+ }
+}