You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2019/12/10 13:39:21 UTC
svn commit: r1871135 - in /jackrabbit/branches/2.18: ./
jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/
jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/
jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/com...
Author: reschke
Date: Tue Dec 10 13:39:21 2019
New Revision: 1871135
URL: http://svn.apache.org/viewvc?rev=1871135&view=rev
Log:
JCR-4502: ISO8601: add convenience methods that do not require passing a Calendar, also support short format without ms information (merged r1869804, r1870503, and r1870756 into 2.18)
Modified:
jackrabbit/branches/2.18/ (props changed)
jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java
jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/package-info.java
jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/ISO8601Test.java
jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/sql/QueryFormat.java
jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/QueryFormat.java
Propchange: jackrabbit/branches/2.18/
------------------------------------------------------------------------------
Merged /jackrabbit/trunk:r1869804,1870503,1870756
Modified: jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java?rev=1871135&r1=1871134&r2=1871135&view=diff
==============================================================================
--- jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java (original)
+++ jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/ISO8601.java Tue Dec 10 13:39:21 2019
@@ -16,10 +16,13 @@
*/
package org.apache.jackrabbit.util;
+import java.time.Clock;
import java.util.Calendar;
+import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
+import java.util.SimpleTimeZone;
import java.util.TimeZone;
/**
@@ -75,6 +78,8 @@ public final class ISO8601 {
}
}
+ private static TimeZone UTC = TimeZone.getTimeZone("UTC");
+
/**
* Parses an ISO8601-compliant date/time string.
*
@@ -226,6 +231,91 @@ public final class ISO8601 {
}
/**
+ * Formats a time instant into an ISO8601-compliant date/time string using
+ * the UTC timezone.
+ *
+ * @param date
+ * date to be formatted
+ * @return the formatted date/time string.
+ * @throws IllegalArgumentException
+ * if the calendar cannot be represented as defined by ISO 8601
+ * (i.e. year with more than four digits).
+ */
+ public static String format(Date date) throws IllegalArgumentException {
+ return format(date, 0);
+ }
+
+ /**
+ * Formats a clock time instant into an ISO8601-compliant date/time string.
+ *
+ * @param clock
+ * clock to obtain time and time zone from
+ * @return the formatted date/time string.
+ * @throws IllegalArgumentException
+ * if the calendar cannot be represented as defined by ISO 8601
+ * (i.e. year with more than four digits).
+ */
+ public static String format(Clock clock) throws IllegalArgumentException {
+ return format(clock.millis(), clock.getZone().getRules().getOffset(clock.instant()).getTotalSeconds());
+ }
+
+ /**
+ * Formats a time instant into an ISO8601-compliant date/time string using
+ * the UTC timezone.
+ *
+ * @param millisSinceEpoch
+ * milliseconds since the epoch
+ * @return the formatted date/time string.
+ * @throws IllegalArgumentException
+ * if the calendar cannot be represented as defined by ISO 8601
+ * (i.e. year with more than four digits).
+ */
+ public static String format(long millisSinceEpoch) throws IllegalArgumentException {
+ return format(millisSinceEpoch, 0);
+ }
+
+ /**
+ * Formats a time instant and a timezone offset into an ISO8601-compliant
+ * date/time string.
+ *
+ * @param date
+ * date to be formatted
+ * @param tzOffsetInSeconds
+ * timezone offset from UTC in seconds
+ * @return the formatted date/time string.
+ * @throws IllegalArgumentException
+ * if the calendar cannot be represented as defined by ISO 8601
+ * (i.e. year with more than four digits).
+ */
+ public static String format(Date date, int tzOffsetInSeconds) throws IllegalArgumentException {
+ if (date == null) {
+ throw new IllegalArgumentException("argument can not be null");
+ }
+ return format(date.getTime(), tzOffsetInSeconds);
+ }
+
+ /**
+ * Formats a time instant and a timezone offset into an ISO8601-compliant
+ * date/time string.
+ *
+ * @param millisSinceEpoch
+ * milliseconds since the epoch
+ * @param tzOffsetInSeconds
+ * timezone offset from UTC in seconds
+ * @return the formatted date/time string.
+ * @throws IllegalArgumentException
+ * if a <code>null</code> argument is passed the calendar cannot
+ * be represented as defined by ISO 8601 (i.e. year with more
+ * than four digits).
+ */
+ public static String format(long millisSinceEpoch, int tzOffsetInSeconds) throws IllegalArgumentException {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(tzOffsetInSeconds == 0 ? UTC : new SimpleTimeZone(tzOffsetInSeconds * 1000, ""));
+ cal.setTimeInMillis(millisSinceEpoch);
+ return format(cal);
+ }
+
+ /**
* Formats a <code>Calendar</code> value into an ISO8601-compliant
* date/time string.
*
@@ -236,6 +326,10 @@ public final class ISO8601 {
* with more than four digits).
*/
public static String format(Calendar cal) throws IllegalArgumentException {
+ return format(cal, true);
+ }
+
+ private static String format(Calendar cal, boolean includeMs) throws IllegalArgumentException {
if (cal == null) {
throw new IllegalArgumentException("argument can not be null");
}
@@ -265,9 +359,11 @@ public final class ISO8601 {
buf.append(':');
// second (ss)
appendZeroPaddedInt(buf, cal.get(Calendar.SECOND), 2);
- buf.append('.');
- // millisecond (SSS)
- appendZeroPaddedInt(buf, cal.get(Calendar.MILLISECOND), 3);
+ if (includeMs) {
+ buf.append('.');
+ // millisecond (SSS)
+ appendZeroPaddedInt(buf, cal.get(Calendar.MILLISECOND), 3);
+ }
// time zone designator (Z or +00:00 or -00:00)
TimeZone tz = cal.getTimeZone();
// determine offset of timezone from UTC (incl. daylight saving)
@@ -313,6 +409,62 @@ public final class ISO8601 {
return year;
}
+
+ /**
+ * Variants that exclude the milliseconds from the formatted string.
+ *
+ */
+ public static class SHORT {
+
+ /**
+ * @see ISO8601#format(Date)
+ */
+ public static String format(Date date) throws IllegalArgumentException {
+ return format(date, 0);
+ }
+
+ /**
+ * @see ISO8601#format(Clock)
+ */
+ public static String format(Clock clock) throws IllegalArgumentException {
+ return format(clock.millis(), clock.getZone().getRules().getOffset(clock.instant()).getTotalSeconds());
+ }
+
+ /**
+ * @see ISO8601#format(long)
+ */
+ public static String format(long millisSinceEpoch) throws IllegalArgumentException {
+ return format(millisSinceEpoch, 0);
+ }
+
+ /**
+ * @see ISO8601#format(Date, int)
+ */
+ public static String format(Date date, int tzOffsetInSeconds) throws IllegalArgumentException {
+ if (date == null) {
+ throw new IllegalArgumentException("argument can not be null");
+ }
+ return format(date.getTime(), tzOffsetInSeconds);
+ }
+
+ /**
+ * @see ISO8601#format(long, int)
+ */
+ public static String format(long millisSinceEpoch, int tzOffsetInSeconds) throws IllegalArgumentException {
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(tzOffsetInSeconds == 0 ? UTC : new SimpleTimeZone(tzOffsetInSeconds * 1000, ""));
+ cal.setTimeInMillis(millisSinceEpoch);
+ return format(cal);
+ }
+
+ /**
+ * @see ISO8601#format(Calendar)
+ */
+ public static String format(Calendar cal) throws IllegalArgumentException {
+ return ISO8601.format(cal, false);
+ }
+ }
+
/**
* Appends a zero-padded number to the given string buffer.
* <p>
Modified: jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/package-info.java?rev=1871135&r1=1871134&r2=1871135&view=diff
==============================================================================
--- jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/package-info.java (original)
+++ jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/package-info.java Tue Dec 10 13:39:21 2019
@@ -14,5 +14,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@org.osgi.annotation.versioning.Version("2.4")
+@org.osgi.annotation.versioning.Version("2.5.0")
package org.apache.jackrabbit.util;
Modified: jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/ISO8601Test.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/ISO8601Test.java?rev=1871135&r1=1871134&r2=1871135&view=diff
==============================================================================
--- jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/ISO8601Test.java (original)
+++ jackrabbit/branches/2.18/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/ISO8601Test.java Tue Dec 10 13:39:21 2019
@@ -16,7 +16,11 @@
*/
package org.apache.jackrabbit.util;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
import java.util.Calendar;
+import java.util.Date;
import java.util.GregorianCalendar;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
@@ -26,11 +30,17 @@ import junit.framework.TestCase;
public class ISO8601Test extends TestCase {
private TimeZone customPlus = new SimpleTimeZone(83 * 60 * 1000, "test");
- private TimeZone customMinus = new SimpleTimeZone(-1202 * 60 * 1000, "test");
+ private TimeZone customMinus = new SimpleTimeZone(-122 * 60 * 1000, "test");
+ private ZoneId customPlusZI = ZoneId.of("+01:23");
+ private ZoneId customMinusZI = ZoneId.of("-02:02");
public void testFormatThrowsIllegalArgumentException() {
try {
- ISO8601.format(null);
+ ISO8601.format((Calendar) null);
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ ISO8601.format((Date) null);
} catch (IllegalArgumentException expected) {
}
}
@@ -45,31 +55,85 @@ public class ISO8601Test extends TestCas
public void testFormatUTC() {
Calendar c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Clock clock;
c.setTimeInMillis(0);
+ clock = Clock.fixed(Instant.ofEpochMilli(0), ZoneId.of("Z"));
assertEquals("1970-01-01T00:00:00.000Z", ISO8601.format(c));
+ assertEquals("1970-01-01T00:00:00.000Z", ISO8601.format(clock));
+ assertEquals("1970-01-01T00:00:00.000Z", ISO8601.format(0));
+ assertEquals("1970-01-01T00:00:00.000Z", ISO8601.format(new Date(0)));
+ assertEquals("1970-01-01T00:00:00.000Z", ISO8601.format(0, 0));
+ assertEquals("1970-01-01T00:00:00.000Z", ISO8601.format(new Date(0), 0));
c.setTimeInMillis(123456789012L);
+ clock = Clock.fixed(Instant.ofEpochMilli(123456789012L), ZoneId.of("Z"));
assertEquals("1973-11-29T21:33:09.012Z", ISO8601.format(c));
+ assertEquals("1973-11-29T21:33:09.012Z", ISO8601.format(clock));
+ assertEquals("1973-11-29T21:33:09.012Z", ISO8601.format(123456789012L));
+ assertEquals("1973-11-29T21:33:09.012Z", ISO8601.format(new Date(123456789012L)));
+ assertEquals("1973-11-29T21:33:09.012Z", ISO8601.format(123456789012L, 0));
+ assertEquals("1973-11-29T21:33:09.012Z", ISO8601.format(new Date(123456789012L), 0));
+ }
+
+ public void testFormatUTCShort() {
+ Calendar c = Calendar.getInstance();
+ c.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Clock clock;
+
+ c.setTimeInMillis(0);
+ clock = Clock.fixed(Instant.ofEpochMilli(0), ZoneId.of("Z"));
+ assertEquals("1970-01-01T00:00:00Z", ISO8601.SHORT.format(c));
+ assertEquals("1970-01-01T00:00:00Z", ISO8601.SHORT.format(clock));
+ assertEquals("1970-01-01T00:00:00Z", ISO8601.SHORT.format(0));
+ assertEquals("1970-01-01T00:00:00Z", ISO8601.SHORT.format(new Date(0)));
+ assertEquals("1970-01-01T00:00:00Z", ISO8601.SHORT.format(0, 0));
+ assertEquals("1970-01-01T00:00:00Z", ISO8601.SHORT.format(new Date(0), 0));
+
+ c.setTimeInMillis(123456789012L);
+ clock = Clock.fixed(Instant.ofEpochMilli(123456789012L), ZoneId.of("Z"));
+ assertEquals("1973-11-29T21:33:09Z", ISO8601.SHORT.format(c));
+ assertEquals("1973-11-29T21:33:09Z", ISO8601.SHORT.format(clock));
+ assertEquals("1973-11-29T21:33:09Z", ISO8601.SHORT.format(123456789012L));
+ assertEquals("1973-11-29T21:33:09Z", ISO8601.SHORT.format(new Date(123456789012L)));
+ assertEquals("1973-11-29T21:33:09Z", ISO8601.SHORT.format(123456789012L, 0));
+ assertEquals("1973-11-29T21:33:09Z", ISO8601.SHORT.format(new Date(123456789012L), 0));
}
public void testFormatCustomTz() {
Calendar c = Calendar.getInstance();
c.setTimeZone(customPlus);
+ Clock clock;
c.setTimeInMillis(0);
+ clock = Clock.fixed(Instant.ofEpochMilli(0), customPlusZI);
assertEquals("1970-01-01T01:23:00.000+01:23", ISO8601.format(c));
+ assertEquals("1970-01-01T01:23:00.000+01:23", ISO8601.format(clock));
+ assertEquals("1970-01-01T01:23:00.000+01:23", ISO8601.format(0, customPlus.getRawOffset() / 1000));
+ assertEquals("1970-01-01T01:23:00.000+01:23", ISO8601.format(new Date(0), customPlus.getRawOffset() / 1000));
c.setTimeInMillis(123456789012L);
+ clock = Clock.fixed(Instant.ofEpochMilli(123456789012L), customPlusZI);
assertEquals("1973-11-29T22:56:09.012+01:23", ISO8601.format(c));
+ assertEquals("1973-11-29T22:56:09.012+01:23", ISO8601.format(clock));
+ assertEquals("1973-11-29T22:56:09.012+01:23", ISO8601.format(123456789012L, customPlus.getRawOffset() / 1000));
+ assertEquals("1973-11-29T22:56:09.012+01:23", ISO8601.format(new Date(123456789012L), customPlus.getRawOffset() / 1000));
c.setTimeZone(customMinus);
c.setTimeInMillis(0);
- assertEquals("1969-12-31T03:58:00.000-20:02", ISO8601.format(c));
+ clock = Clock.fixed(Instant.ofEpochMilli(0), customMinusZI);
+ assertEquals("1969-12-31T21:58:00.000-02:02", ISO8601.format(c));
+ assertEquals("1969-12-31T21:58:00.000-02:02", ISO8601.format(clock));
+ assertEquals("1969-12-31T21:58:00.000-02:02", ISO8601.format(0, customMinus.getRawOffset() / 1000));
+ assertEquals("1969-12-31T21:58:00.000-02:02", ISO8601.format(new Date(0), customMinus.getRawOffset() / 1000));
c.setTimeInMillis(123456789012L);
- assertEquals("1973-11-29T01:31:09.012-20:02", ISO8601.format(c));
+ clock = Clock.fixed(Instant.ofEpochMilli(123456789012L), customMinusZI);
+ assertEquals("1973-11-29T19:31:09.012-02:02", ISO8601.format(c));
+ assertEquals("1973-11-29T19:31:09.012-02:02", ISO8601.format(clock));
+ assertEquals("1973-11-29T19:31:09.012-02:02", ISO8601.format(123456789012L, customMinus.getRawOffset() / 1000));
+ assertEquals("1973-11-29T19:31:09.012-02:02", ISO8601.format(new Date(123456789012L), customMinus.getRawOffset() / 1000));
}
public void testParseUTC() {
@@ -91,11 +155,11 @@ public class ISO8601Test extends TestCas
assertEquals(123456789012L, c.getTimeInMillis());
assertEquals(customPlus.getRawOffset(), c.getTimeZone().getRawOffset());
- c = ISO8601.parse("1969-12-31T03:58:00.000-20:02");
+ c = ISO8601.parse("1969-12-31T21:58:00.000-02:02");
assertEquals(0, c.getTimeInMillis());
assertEquals(customMinus.getRawOffset(), c.getTimeZone().getRawOffset());
- c = ISO8601.parse("1973-11-29T01:31:09.012-20:02");
+ c = ISO8601.parse("1973-11-29T19:31:09.012-02:02");
assertEquals(123456789012L, c.getTimeInMillis());
assertEquals(customMinus.getRawOffset(), c.getTimeZone().getRawOffset());
}
Modified: jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/sql/QueryFormat.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/sql/QueryFormat.java?rev=1871135&r1=1871134&r2=1871135&view=diff
==============================================================================
--- jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/sql/QueryFormat.java (original)
+++ jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/sql/QueryFormat.java Tue Dec 10 13:39:21 2019
@@ -17,10 +17,8 @@
package org.apache.jackrabbit.spi.commons.query.sql;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
-import java.util.TimeZone;
import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;
@@ -553,9 +551,7 @@ class QueryFormat implements QueryNodeVi
} else if (node.getValueType() == TYPE_STRING) {
b.append("'").append(node.getStringValue().replaceAll("'", "''")).append("'");
} else if (node.getValueType() == TYPE_DATE || node.getValueType() == TYPE_TIMESTAMP) {
- Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- cal.setTime(node.getDateValue());
- b.append("TIMESTAMP '").append(ISO8601.format(cal)).append("'");
+ b.append("TIMESTAMP '").append(ISO8601.format(node.getDateValue())).append("'");
} else {
exceptions.add(new InvalidQueryException("Invalid type: " + node.getValueType()));
}
Modified: jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/QueryFormat.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/QueryFormat.java?rev=1871135&r1=1871134&r2=1871135&view=diff
==============================================================================
--- jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/QueryFormat.java (original)
+++ jackrabbit/branches/2.18/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/query/xpath/QueryFormat.java Tue Dec 10 13:39:21 2019
@@ -17,9 +17,7 @@
package org.apache.jackrabbit.spi.commons.query.xpath;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.List;
-import java.util.TimeZone;
import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;
@@ -505,10 +503,8 @@ class QueryFormat implements QueryNodeVi
} else if (node.getValueType() == TYPE_STRING) {
b.append("'").append(node.getStringValue().replaceAll("'", "''")).append("'");
} else if (node.getValueType() == TYPE_DATE || node.getValueType() == TYPE_TIMESTAMP) {
- Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- cal.setTime(node.getDateValue());
b.append(resolver.getJCRName(XPathQueryBuilder.XS_DATETIME));
- b.append("('").append(ISO8601.format(cal)).append("')");
+ b.append("('").append(ISO8601.format(node.getDateValue())).append("')");
} else if (node.getValueType() == TYPE_POSITION) {
if (node.getPositionValue() == LocationStepQueryNode.LAST) {
b.append("last()");