[java-support] branch master updated: JSPT-79 - Review date and time handling for Java 8
Ian Young
ian at iay.org.uk
Wed Mar 20 11:56:02 EDT 2019
This is an automated email from the git hooks/post-receive script.
iay pushed a commit to branch master
in repository java-support.
View the commit online:
http://git.shibboleth.net/view/?p=java-support.git;a=commit;h=a54e14305561cba4f4103041b41b436ee2ff3822
The following commit(s) were added to refs/heads/master by this push:
new a54e143 JSPT-79 - Review date and time handling for Java 8
a54e143 is described below
commit a54e14305561cba4f4103041b41b436ee2ff3822
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Wed Mar 20 15:55:56 2019 +0000
JSPT-79 - Review date and time handling for Java 8
Change AttributeSupport to have a long-clean API for instants and durations.
Related changes made in DOMTypeSupport, not yet complete.
---
.../java/support/xml/AttributeSupport.java | 37 +++++++++++--------
.../utilities/java/support/xml/DOMTypeSupport.java | 23 ++++++++----
.../java/support/xml/AttributeSupportTest.java | 43 ++++++++++++----------
.../java/support/xml/DomTypeSupportTest.java | 14 ++-----
4 files changed, 66 insertions(+), 51 deletions(-)
diff --git a/src/main/java/net/shibboleth/utilities/java/support/xml/AttributeSupport.java b/src/main/java/net/shibboleth/utilities/java/support/xml/AttributeSupport.java
index 9375a9c..4afe75a 100644
--- a/src/main/java/net/shibboleth/utilities/java/support/xml/AttributeSupport.java
+++ b/src/main/java/net/shibboleth/utilities/java/support/xml/AttributeSupport.java
@@ -17,6 +17,8 @@
package net.shibboleth.utilities.java.support.xml;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
@@ -155,16 +157,21 @@ public final class AttributeSupport {
}
/**
- * Adds an attribute to the given element. The value of the attribute is the instant now + the given duration
+ * Adds an attribute to the given element. The value of the attribute is the given instant
* expressed in XML dateTime format.
+ *
+ * Note that simply using <code>instant.toString()</code> is equivalent for many use cases, but
+ * the result will be different on a system with a higher-resolution clock, as the resulting
+ * string value may have sub-millisecond precision. This method always works to millisecond
+ * precision.
*
* @param element element to which the attribute will be added, not null
* @param attributeName name of the attribute, not null
- * @param duration duration, in milliseconds, must be greater than 0
+ * @param instant instant to set into the attribute, not null
*/
public static void appendDateTimeAttribute(@Nonnull final Element element, @Nonnull final QName attributeName,
- final long duration) {
- appendAttribute(element, attributeName, DOMTypeSupport.longToDateTime(duration));
+ @Nonnull final Instant instant) {
+ appendAttribute(element, attributeName, DOMTypeSupport.instantToDateTime(instant));
}
/**
@@ -172,11 +179,11 @@ public final class AttributeSupport {
*
* @param element element to which the attribute will be added, not null
* @param attributeName name of the attribute, not null
- * @param duration duration, in milliseconds, must be greater than 0
+ * @param duration duration, must be greater than 0
*/
public static void appendDurationAttribute(@Nonnull final Element element, @Nonnull final QName attributeName,
- final long duration) {
- appendAttribute(element, attributeName, DOMTypeSupport.longToDuration(duration));
+ @Nonnull final Duration duration) {
+ appendAttribute(element, attributeName, DOMTypeSupport.longToDuration(duration.toMillis()));
}
/**
@@ -346,33 +353,33 @@ public final class AttributeSupport {
}
/**
- * Gets the value of a dateTime-type attribute in milliseconds since the epoch.
+ * Gets the value of a dateTime-type attribute as an {@link Instant}.
*
* @param attribute attribute from which to extract the value, may be null
*
- * @return date/time in millisecond since the epoch, or null if the attribute was null
+ * @return date/time as an {@link Instant}, or null if the attribute was null
*/
- @Nullable public static Long getDateTimeAttributeAsLong(@Nullable final Attr attribute) {
+ @Nullable public static Instant getDateTimeAttribute(@Nullable final Attr attribute) {
if (attribute == null || StringSupport.trimOrNull(attribute.getValue()) == null) {
return null;
}
- return DOMTypeSupport.dateTimeToLong(attribute.getValue());
+ return DOMTypeSupport.dateTimeToInstant(attribute.getValue());
}
/**
- * Gets the value of a duration-type attribute in milliseconds.
+ * Gets the value of a duration-type attribute as a {@link Duration}.
*
* @param attribute attribute from which to extract the value, may be null
*
- * @return duration, in millisecond, or null if the attribute was null
+ * @return duration, or null if the attribute was null
*/
- @Nullable public static Long getDurationAttributeValueAsLong(@Nullable final Attr attribute) {
+ @Nullable public static Duration getDurationAttributeValue(@Nullable final Attr attribute) {
if (attribute == null || StringSupport.trimOrNull(attribute.getValue()) == null) {
return null;
}
- return DOMTypeSupport.durationToLong(attribute.getValue());
+ return DOMTypeSupport.durationToDuration(attribute.getValue());
}
/**
diff --git a/src/main/java/net/shibboleth/utilities/java/support/xml/DOMTypeSupport.java b/src/main/java/net/shibboleth/utilities/java/support/xml/DOMTypeSupport.java
index 8c68872..c3bf4ca 100644
--- a/src/main/java/net/shibboleth/utilities/java/support/xml/DOMTypeSupport.java
+++ b/src/main/java/net/shibboleth/utilities/java/support/xml/DOMTypeSupport.java
@@ -17,6 +17,7 @@
package net.shibboleth.utilities.java.support.xml;
+import java.time.Instant;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
@@ -49,18 +50,18 @@ public final class DOMTypeSupport {
}
/**
- * Converts a lexical dateTime, as defined by XML Schema 1.0, into milliseconds since the epoch.
+ * Converts a lexical dateTime, as defined by XML Schema 1.0, into an {@link Instant}.
*
* @param dateTime lexical date/time, may not be null
*
- * @return the date/time expressed as milliseconds since the epoch
+ * @return the date/time expressed as an {@link Instant}
*/
- public static long dateTimeToLong(@Nonnull final String dateTime) {
+ public static Instant dateTimeToInstant(@Nonnull final String dateTime) {
final String trimmedString =
Constraint.isNotNull(StringSupport.trimOrNull(dateTime), "Lexical dateTime may not be null or empty");
final XMLGregorianCalendar calendar = dataTypeFactory.newXMLGregorianCalendar(trimmedString);
- return calendar.toGregorianCalendar().getTimeInMillis();
+ return calendar.toGregorianCalendar().toInstant();
}
/**
@@ -70,6 +71,7 @@ public final class DOMTypeSupport {
*
* @return duration in milliseconds
*/
+ @Deprecated
public static long durationToLong(final String duration) {
return dataTypeFactory.newDuration(duration).getTimeInMillis(baseline);
}
@@ -81,6 +83,7 @@ public final class DOMTypeSupport {
*
* @return duration in milliseconds
*/
+ @Deprecated
public static long durationToLong(final Duration duration) {
return duration.getTimeInMillis(baseline);
}
@@ -139,17 +142,22 @@ public final class DOMTypeSupport {
}
/**
- * Converts a numerical date/time, given in milliseconds since the epoch, to a lexical dateTime defined by XML
+ * Converts a numerical date/time, given as an {@link Instant}, to a lexical dateTime defined by XML
* Schema 1.0.
*
+ * Note that simply using <code>instant.toString()</code> is equivalent for many use cases, but
+ * the result will be different on a system with a higher-resolution clock, as the resulting
+ * string value may have sub-millisecond precision. This method always works to millisecond
+ * precision.
+ *
* @param dateTime the date time to be converted
*
* @return the lexical representation of the date/time
*/
- @Nonnull public static String longToDateTime(final long dateTime) {
+ @Nonnull public static String instantToDateTime(@Nonnull final Instant dateTime) {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
- calendar.setTimeInMillis(dateTime);
+ calendar.setTimeInMillis(dateTime.toEpochMilli());
return dataTypeFactory.newXMLGregorianCalendar(calendar).normalize().toXMLFormat();
}
@@ -161,6 +169,7 @@ public final class DOMTypeSupport {
*
* @return the lexical representation
*/
+ @Deprecated
@Nonnull public static String longToDuration(final long duration) {
return dataTypeFactory.newDuration(duration).toString();
}
diff --git a/src/test/java/net/shibboleth/utilities/java/support/xml/AttributeSupportTest.java b/src/test/java/net/shibboleth/utilities/java/support/xml/AttributeSupportTest.java
index 676229a..54c79bb 100644
--- a/src/test/java/net/shibboleth/utilities/java/support/xml/AttributeSupportTest.java
+++ b/src/test/java/net/shibboleth/utilities/java/support/xml/AttributeSupportTest.java
@@ -18,6 +18,9 @@
package net.shibboleth.utilities.java.support.xml;
import java.io.IOException;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -423,29 +426,29 @@ public class AttributeSupportTest {
Assert.assertEquals(AttributeSupport.getAttributeValueAsQName(AttributeSupport.getAttribute(attributes,
new QName(TEST_NS, "testAttrZero"))), new QName("0"), "attribute called testAttrZero");
- // getDateTimeAttributeAsLong
+ // getDateTimeAttribute
// Use the previously tested AttributeSupport.getAttribute
- Assert.assertNull(AttributeSupport.getDateTimeAttributeAsLong(null), "null attribute should be null");
- Assert.assertNull(AttributeSupport.getDateTimeAttributeAsLong(AttributeSupport.getAttribute(attributes,
+ Assert.assertNull(AttributeSupport.getDateTimeAttribute(null), "null attribute should be null");
+ Assert.assertNull(AttributeSupport.getDateTimeAttribute(AttributeSupport.getAttribute(attributes,
new QName(TEST_NS, "testAttrEmpty"))), "\"\" should be null");
- Assert.assertNull(AttributeSupport.getDateTimeAttributeAsLong(AttributeSupport.getAttribute(attributes,
+ Assert.assertNull(AttributeSupport.getDateTimeAttribute(AttributeSupport.getAttribute(attributes,
new QName(TEST_NS, "testAttrEmpty"))), "\"0\" should be null");
Assert.assertEquals(
- AttributeSupport.getDateTimeAttributeAsLong(
- AttributeSupport.getAttribute(attributes, new QName(TEST_NS, "testAttrEpochPlusOneSec")))
- .intValue(), 1000, "attribute called testAttrEpochPlusOneSec");
+ AttributeSupport.getDateTimeAttribute(
+ AttributeSupport.getAttribute(attributes, new QName(TEST_NS, "testAttrEpochPlusOneSec"))),
+ Instant.ofEpochSecond(1), "attribute called testAttrEpochPlusOneSec");
// getDurationAttributeValueAsLong
// Use the previously tested AttributeSupport.getAttribute
- Assert.assertNull(AttributeSupport.getDurationAttributeValueAsLong(null), "null attribute should be null");
- Assert.assertNull(AttributeSupport.getDurationAttributeValueAsLong(AttributeSupport.getAttribute(attributes,
+ Assert.assertNull(AttributeSupport.getDurationAttributeValue(null), "null attribute should be null");
+ Assert.assertNull(AttributeSupport.getDurationAttributeValue(AttributeSupport.getAttribute(attributes,
new QName(TEST_NS, "testAttrEmpty"))), "\"\" should be null");
- Assert.assertNull(AttributeSupport.getDurationAttributeValueAsLong(AttributeSupport.getAttribute(attributes,
+ Assert.assertNull(AttributeSupport.getDurationAttributeValue(AttributeSupport.getAttribute(attributes,
new QName(TEST_NS, "testAttrEmpty"))), "\"0\" should be null");
Assert.assertEquals(
- AttributeSupport.getDurationAttributeValueAsLong(
- AttributeSupport.getAttribute(attributes, new QName(TEST_NS, "testAttrMinusOneDay")))
- .intValue(), -24 * 60 * 60 * 1000, "attribute called testAttrMinusOneDay");
+ AttributeSupport.getDurationAttributeValue(
+ AttributeSupport.getAttribute(attributes, new QName(TEST_NS, "testAttrMinusOneDay"))),
+ Duration.ofDays(-1), "attribute called testAttrMinusOneDay");
}
@Test(dependsOnMethods = {"testGetAttributeMethods", "testGetID"}) public void testAppends() {
@@ -592,7 +595,7 @@ public class AttributeSupportTest {
Assert.assertEquals(AttributeSupport.getIdAttribute(createdElement).getValue(), testResult,
"id Attribute added correctly");
- int duration = 1000;
+ final var duration = Duration.ofSeconds(1);
qNameBase = qNameBase + "New";
qName = new QName(TEST_NS, qNameBase, TEST_PREFIX);
Assert.assertNull(AttributeSupport.getAttributeValue(createdElement, qName), "Test precondition");
@@ -620,10 +623,12 @@ public class AttributeSupportTest {
}
Assert.assertFalse(thrown, "All non nulls should not throw");
Assert.assertEquals(
- AttributeSupport.getDurationAttributeValueAsLong(AttributeSupport.getAttribute(createdElement, qName))
- .intValue(), duration, "getDurationAttributeValueAsLong failed");
+ AttributeSupport.getDurationAttributeValue(AttributeSupport.getAttribute(createdElement, qName)),
+ duration, "getDurationAttributeValueAsLong failed");
- long time = 1000 * 60 * 60 * 24;
+ // Construct a time that contains nothing below the level of milliseconds,
+ // for compatibility with representations that don't have higher precision.
+ final var time = Instant.now().truncatedTo(ChronoUnit.MILLIS);
qNameBase = qNameBase + "New";
qName = new QName(TEST_NS, qNameBase, TEST_PREFIX);
Assert.assertNull(AttributeSupport.getAttributeValue(createdElement, qName), "Test precondition");
@@ -651,8 +656,8 @@ public class AttributeSupportTest {
}
Assert.assertFalse(thrown, "All non nulls should not throw");
Assert.assertEquals(
- AttributeSupport.getDateTimeAttributeAsLong(AttributeSupport.getAttribute(createdElement, qName))
- .intValue(), time, "getDurationAttributeValueAsLong failed");
+ AttributeSupport.getDateTimeAttribute(AttributeSupport.getAttribute(createdElement, qName)),
+ time, "getDurationAttributeValueAsLong failed");
}
diff --git a/src/test/java/net/shibboleth/utilities/java/support/xml/DomTypeSupportTest.java b/src/test/java/net/shibboleth/utilities/java/support/xml/DomTypeSupportTest.java
index 14b7ffa..c6db94c 100644
--- a/src/test/java/net/shibboleth/utilities/java/support/xml/DomTypeSupportTest.java
+++ b/src/test/java/net/shibboleth/utilities/java/support/xml/DomTypeSupportTest.java
@@ -18,6 +18,7 @@
package net.shibboleth.utilities.java.support.xml;
import java.io.IOException;
+import java.time.Instant;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
@@ -60,16 +61,9 @@ public class DomTypeSupportTest {
}
- @Test public void testDateTimeToLong() {
- Assert.assertEquals(DOMTypeSupport.dateTimeToLong("1970-01-01T00:00:01Z"), 1000, "Epoch plus one second");
- Assert.assertEquals(DOMTypeSupport.dateTimeToLong("1969-12-31T23:59:59Z"), -1000, "Epoch minus one second");
- Assert.assertEquals(DOMTypeSupport.dateTimeToLong("1970-01-01T00:00:00-05:00"), 5 * 3600 * 1000,
- "Epoch minus 5 hours timezone");
- }
-
- @Test public void testLongToDateTime() {
- Assert.assertEquals(DOMTypeSupport.longToDateTime(1000), "1970-01-01T00:00:01.000Z", "Epoch plus one second");
- Assert.assertEquals(DOMTypeSupport.longToDateTime(-1000), "1969-12-31T23:59:59.000Z", "Epoch minus one second");
+ @Test public void testInstantToDateTime() {
+ Assert.assertEquals(DOMTypeSupport.instantToDateTime(Instant.EPOCH.plusMillis(1000)), "1970-01-01T00:00:01.000Z", "Epoch plus one second");
+ Assert.assertEquals(DOMTypeSupport.instantToDateTime(Instant.EPOCH.plusMillis(-1000)), "1969-12-31T23:59:59.000Z", "Epoch minus one second");
}
@Test public void testDurationToLong() {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list