diff --git a/README.md b/README.md
index 79823d6..280dcd5 100644
--- a/README.md
+++ b/README.md
@@ -27,18 +27,23 @@ W3C [Date and Time Formats](https://www.w3.org/TR/NOTE-datetime) in Java.
-| Implementation | Parse | Format | Round-trip |
--------------------|--------:|----------:|-----:|
-| Google DateTime | 1,020 ns | Not supported | N/A
-| JDK Java Time | 1,558 ns | 426 ns | 1,984 ns |
-| Ethlo ITU | 88 ns |166 ns |254 ns|
+| Implementation | Parse | Format |
+-------------------|--------:|----------:|
+| Google DateTime | 885,089 | Not supported
+| JDK Java Time | 739,180 | 2,406,040
+| Ethlo ITU | 12,437,143 | 12,602,170
-Values in nano-seconds. Lower is better.
+Numbers are operations per second (higher is better).
Your mileage may vary. The tests are easy to run and are included in the repository.
-## Example use
+Tests performed on a Dell XPS 9700
+* Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
+* Ubuntu 21.10
+* OpenJDK version 11.0.13
+
+## Example usage
```java
// Parse a string
diff --git a/doc/performance.jpg b/doc/performance.jpg
index 62a08f9..72c7447 100644
Binary files a/doc/performance.jpg and b/doc/performance.jpg differ
diff --git a/src/main/java/com/ethlo/time/EthloITU.java b/src/main/java/com/ethlo/time/EthloITU.java
index d4be14e..d83bbf9 100644
--- a/src/main/java/com/ethlo/time/EthloITU.java
+++ b/src/main/java/com/ethlo/time/EthloITU.java
@@ -20,17 +20,21 @@
* #L%
*/
+import static com.ethlo.time.LimitedCharArrayIntegerUtil.indexOfNonDigit;
+import static com.ethlo.time.LimitedCharArrayIntegerUtil.parsePositiveInt;
+
import java.time.DateTimeException;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.time.Month;
import java.time.OffsetDateTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.util.Arrays;
import java.util.Date;
+import java.util.Objects;
public class EthloITU extends AbstractRfc3339 implements W3cDateTimeUtil
{
@@ -49,18 +53,81 @@ public class EthloITU extends AbstractRfc3339 implements W3cDateTimeUtil
private final Java8Rfc3339 delegate = new Java8Rfc3339();
@Override
- public OffsetDateTime parseDateTime(String s)
+ public OffsetDateTime parseDateTime(String text)
+ {
+ Objects.requireNonNull(text, "text");
+ final char[] chars = text.toCharArray();
+
+ final int year = getYear(chars);
+
+ assertPositionContains(chars, 4, DATE_SEPARATOR);
+ final int month = getMonth(chars);
+
+ assertPositionContains(chars, 7, DATE_SEPARATOR);
+ final int day = getDay(chars);
+
+ // *** Time starts ***//
+
+ // HOURS
+ assertPositionContains(chars, 10, SEPARATOR_UPPER, SEPARATOR_LOWER, SEPARATOR_SPACE);
+ final int hour = getHour(chars);
+
+ // MINUTES
+ assertPositionContains(chars, 13, TIME_SEPARATOR);
+ final int minute = getMinute(chars);
+
+ // SECONDS or TIMEZONE
+ return handleTime(chars, year, month, day, hour, minute);
+ }
+
+ private int getHour(final char[] chars)
{
- final Temporal t = doParseLenient(s, OffsetDateTime.class);
- if (t == null)
+ return parsePositiveInt(chars, 11, 13);
+ }
+
+ private int getMinute(final char[] chars)
+ {
+ return parsePositiveInt(chars, 14, 16);
+ }
+
+ private int getDay(final char[] chars)
+ {
+ return parsePositiveInt(chars, 8, 10);
+ }
+
+ private OffsetDateTime handleTime(char[] chars, int year, int month, int day, int hour, int minute)
+ {
+ switch (chars[16])
{
- return null;
+ // We have more granularity, keep going
+ case TIME_SEPARATOR:
+ return seconds(year, month, day, hour, minute, chars);
+
+ case PLUS:
+ case MINUS:
+ case ZULU_UPPER:
+ case ZULU_LOWER:
+ final ZoneOffset zoneOffset = parseTz(chars, 16);
+ return OffsetDateTime.of(year, month, day, hour, minute, 0, 0, zoneOffset);
+
+ default:
+ assertPositionContains(chars, 16, TIME_SEPARATOR, PLUS, MINUS, ZULU_UPPER);
}
- else if (t instanceof OffsetDateTime)
+ throw new DateTimeException(new String(chars));
+ }
+
+ private void assertPositionContains(char[] chars, int offset, char expected)
+ {
+ if (offset >= chars.length)
{
- return (OffsetDateTime) t;
+ throw new DateTimeException("Abrupt end of input: " + new String(chars));
+ }
+
+ if (chars[offset] != expected)
+ {
+ throw new DateTimeException("Expected character " + expected
+ + " at position " + (offset + 1) + " '" + new String(chars) + "'");
}
- throw new DateTimeException("Invalid RFC-3339 date-time: " + s);
}
private void assertPositionContains(char[] chars, int offset, char... expected)
@@ -101,8 +168,8 @@ private ZoneOffset parseTz(char[] chars, int offset)
}
final char sign = chars[offset];
- int hours = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, offset + 1, offset + 3);
- int minutes = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, offset + 4, offset + 4 + 2);
+ int hours = parsePositiveInt(chars, offset + 1, offset + 3);
+ int minutes = parsePositiveInt(chars, offset + 4, offset + 4 + 2);
if (sign == MINUS)
{
hours = -hours;
@@ -144,25 +211,25 @@ public String format(OffsetDateTime date, Field lastIncluded)
public String formatUtc(OffsetDateTime date, Field lastIncluded, int fractionDigits)
{
assertMaxFractionDigits(fractionDigits);
- final LocalDateTime utc = LocalDateTime.ofInstant(date.toInstant(), ZoneOffset.UTC);
+ final ZonedDateTime utc = date.atZoneSameInstant(ZoneOffset.UTC);
final char[] buffer = new char[31];
if (handleDatePart(lastIncluded, buffer, utc.getYear(), 0, 4, Field.YEAR))
{
- return finish(buffer, 4);
+ return finish(buffer, Field.YEAR.getRequiredLength());
}
buffer[4] = DATE_SEPARATOR;
if (handleDatePart(lastIncluded, buffer, utc.getMonthValue(), 5, 2, Field.MONTH))
{
- return finish(buffer, 7);
+ return finish(buffer, Field.MONTH.getRequiredLength());
}
buffer[7] = DATE_SEPARATOR;
if (handleDatePart(lastIncluded, buffer, utc.getDayOfMonth(), 8, 2, Field.DAY))
{
- return finish(buffer, 10);
+ return finish(buffer, Field.DAY.getRequiredLength());
}
// T separator
@@ -173,7 +240,7 @@ public String formatUtc(OffsetDateTime date, Field lastIncluded, int fractionDig
buffer[13] = TIME_SEPARATOR;
if (handleDatePart(lastIncluded, buffer, utc.getMinute(), 14, 2, Field.MINUTE))
{
- return finish(buffer, 16);
+ return finish(buffer, Field.MINUTE.getRequiredLength());
}
buffer[16] = TIME_SEPARATOR;
LimitedCharArrayIntegerUtil.toString(utc.getSecond(), buffer, 17, 2);
@@ -301,7 +368,7 @@ public Temporal doParseLenient(String s, Class type)
// Date portion
// YEAR
- final int year = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, 0, 4);
+ final int year = getYear(chars);
if (maxRequired == Field.YEAR || chars.length == 4)
{
return Year.of(year);
@@ -309,7 +376,7 @@ public Temporal doParseLenient(String s, Class type)
// MONTH
assertPositionContains(chars, 4, DATE_SEPARATOR);
- final int month = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, 5, 7);
+ final int month = getMonth(chars);
if (maxRequired == Field.MONTH || chars.length == 7)
{
return YearMonth.of(year, month);
@@ -317,49 +384,41 @@ public Temporal doParseLenient(String s, Class type)
// DAY
assertPositionContains(chars, 7, DATE_SEPARATOR);
- final int day = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, 8, 10);
+ final int day = getDay(chars);
if (maxRequired == Field.DAY || chars.length == 10)
{
return LocalDate.of(year, month, day);
}
- // *** Time starts ***//
-
// HOURS
assertPositionContains(chars, 10, SEPARATOR_UPPER, SEPARATOR_LOWER, SEPARATOR_SPACE);
- final int hour = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, 11, 13);
+ final int hour = getHour(chars);
// MINUTES
assertPositionContains(chars, 13, TIME_SEPARATOR);
- final int minute = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, 14, 16);
+ final int minute = getMinute(chars);
if (maxRequired == Field.MINUTE || chars.length == 16)
{
return LocalDate.of(year, month, day);
}
// SECONDS or TIMEZONE
- switch (chars[16])
- {
- // We have more granularity, keep going
- case TIME_SEPARATOR:
- return seconds(year, month, day, hour, minute, chars);
+ return handleTime(chars, year, month, day, hour, minute);
+ }
- case PLUS:
- case MINUS:
- case ZULU_UPPER:
- case ZULU_LOWER:
- final ZoneOffset zoneOffset = parseTz(chars, 16);
- return OffsetDateTime.of(year, month, day, hour, minute, 0, 0, zoneOffset);
+ private int getMonth(final char[] chars)
+ {
+ return parsePositiveInt(chars, 5, 7);
+ }
- default:
- assertPositionContains(chars, 16, TIME_SEPARATOR, PLUS, MINUS, ZULU_UPPER);
- }
- throw new DateTimeException(new String(chars));
+ private int getYear(final char[] chars)
+ {
+ return parsePositiveInt(chars, 0, 4);
}
private OffsetDateTime seconds(int year, int month, int day, int hour, int minute, char[] chars)
{
- final int second = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, 17, 19);
+ final int second = getSecond(chars);
// From here the specification is more lenient
final int remaining = chars.length - 19;
@@ -376,7 +435,7 @@ private OffsetDateTime seconds(int year, int month, int day, int hour, int minut
else if (remaining >= 1 && chars[19] == FRACTION_SEPARATOR)
{
// We have fractional seconds
- final int idx = LimitedCharArrayIntegerUtil.indexOfNonDigit(chars, 20);
+ final int idx = indexOfNonDigit(chars, 20);
if (idx != -1)
{
// We have an end of fractions
@@ -419,10 +478,15 @@ else if (remaining == 0)
return OffsetDateTime.of(year, month, day, hour, minute, second, fractions, offset);
}
+ private int getSecond(final char[] chars)
+ {
+ return parsePositiveInt(chars, 17, 19);
+ }
+
private int getFractions(final char[] chars, final int idx, final int len)
{
final int fractions;
- fractions = LimitedCharArrayIntegerUtil.parsePositiveInt(chars, 20, idx);
+ fractions = parsePositiveInt(chars, 20, idx);
switch (len)
{
case 1:
diff --git a/src/main/java/com/ethlo/time/Field.java b/src/main/java/com/ethlo/time/Field.java
index 881adce..ba450eb 100644
--- a/src/main/java/com/ethlo/time/Field.java
+++ b/src/main/java/com/ethlo/time/Field.java
@@ -29,7 +29,14 @@
public enum Field
{
// 2000-12-31T16:11:34.123456
- YEAR, MONTH, DAY, MINUTE, SECOND;
+ YEAR(4), MONTH(7), DAY(10), MINUTE(16), SECOND(19);
+
+ private final int requiredLength;
+
+ Field(int requiredLength)
+ {
+ this.requiredLength = requiredLength;
+ }
public static Field valueOf(Class extends Temporal> type)
{
@@ -52,4 +59,9 @@ else if (OffsetDateTime.class.equals(type))
throw new IllegalArgumentException("Type " + type.getSimpleName() + " is not supported");
}
+
+ public int getRequiredLength()
+ {
+ return requiredLength;
+ }
}
diff --git a/src/main/java/com/ethlo/time/Java8Rfc3339.java b/src/main/java/com/ethlo/time/Java8Rfc3339.java
index aff202c..c06a894 100644
--- a/src/main/java/com/ethlo/time/Java8Rfc3339.java
+++ b/src/main/java/com/ethlo/time/Java8Rfc3339.java
@@ -38,9 +38,9 @@
*/
public class Java8Rfc3339 extends AbstractRfc3339
{
- private SimpleDateFormat[] formats = new SimpleDateFormat[MAX_FRACTION_DIGITS];
+ private final SimpleDateFormat[] formats = new SimpleDateFormat[MAX_FRACTION_DIGITS];
- private DateTimeFormatter rfc3339baseFormatter = new DateTimeFormatterBuilder()
+ private final DateTimeFormatter rfc3339baseFormatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
@@ -53,7 +53,8 @@ public class Java8Rfc3339 extends AbstractRfc3339
.appendLiteral(':')
.appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.toFormatter();
- private DateTimeFormatter rfc3339formatParser = new DateTimeFormatterBuilder()
+
+ private final DateTimeFormatter rfc3339formatParser = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
@@ -83,14 +84,13 @@ public class Java8Rfc3339 extends AbstractRfc3339
.optionalStart()
.appendOffset("+HH:MM", "z")
.optionalEnd()
-
.toFormatter();
public Java8Rfc3339()
{
for (int i = 1; i < MAX_FRACTION_DIGITS; i++)
{
- this.formats[i] = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss." + repeat('S', i) + "XXX");
+ this.formats[i] = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss." + repeat(i) + "XXX");
}
}
@@ -125,18 +125,13 @@ public String formatUtc(Date date)
@Override
public OffsetDateTime parseDateTime(final String s)
{
- if (s == null || s.isEmpty())
- {
- return null;
- }
-
return OffsetDateTime.from(rfc3339formatParser.parse(s));
}
- private String repeat(char c, int repeats)
+ private String repeat(int repeats)
{
final char[] chars = new char[repeats];
- Arrays.fill(chars, c);
+ Arrays.fill(chars, 'S');
return new String(chars);
}
diff --git a/src/main/java/com/ethlo/time/LimitedCharArrayIntegerUtil.java b/src/main/java/com/ethlo/time/LimitedCharArrayIntegerUtil.java
index 2471f93..880f959 100644
--- a/src/main/java/com/ethlo/time/LimitedCharArrayIntegerUtil.java
+++ b/src/main/java/com/ethlo/time/LimitedCharArrayIntegerUtil.java
@@ -57,7 +57,7 @@ public static int parsePositiveInt(char[] strNum, int startInclusive, int endExc
int result = 0;
for (int i = startInclusive; i < endExclusive; i++)
{
- if (!isDigit(strNum[i]))
+ if (isNotDigit(strNum[i]))
{
throw new DateTimeException("Character " + strNum[i] + " is not a digit");
}
@@ -81,7 +81,7 @@ private static void toString(final int val, final char[] buf, final int offset,
final int length = Math.min(TABLE_WIDTH, charLength);
final int padPrefixLen = charLength - length;
final int start = charLength > TABLE_WIDTH ? TABLE_WIDTH : TABLE_WIDTH - charLength;
- final int targetOffset = offset + (Math.max(padPrefixLen, 0));
+ final int targetOffset = offset + padPrefixLen;
final int srcPos = (value * TABLE_WIDTH) + (charLength < TABLE_WIDTH ? start : 0);
copy(INT_CONVERSION_CACHE, srcPos, buf, targetOffset, length);
if (padPrefixLen > 0)
@@ -89,28 +89,30 @@ private static void toString(final int val, final char[] buf, final int offset,
zeroFill(buf, offset, padPrefixLen);
}
}
-
- int charPos = offset + MAX_INT_WIDTH;
- value = -value;
- int div;
- int rem;
- while (value <= -10)
+ else
{
- div = value / 10;
- rem = -(value - 10 * div);
- buf[charPos--] = DIGITS[rem];
- value = div;
- }
- buf[charPos] = DIGITS[-value];
+ int charPos = offset + MAX_INT_WIDTH;
+ value = -value;
+ int div;
+ int rem;
+ while (value <= -10)
+ {
+ div = value / 10;
+ rem = -(value - 10 * div);
+ buf[charPos--] = DIGITS[rem];
+ value = div;
+ }
+ buf[charPos] = DIGITS[-value];
- int l = ((MAX_INT_WIDTH + offset) - charPos) + 1;
- while (l < charLength)
- {
- buf[--charPos] = ZERO;
- l++;
+ int l = ((MAX_INT_WIDTH + offset) - charPos) + 1;
+ while (l < charLength)
+ {
+ buf[--charPos] = ZERO;
+ l++;
+ }
+ final int srcPos = charPos;
+ copy(buf, srcPos, offset, charLength);
}
- final int srcPos = charPos;
- copy(buf, srcPos, offset, charLength);
}
private static void zeroFill(char[] buf, int offset, int padPrefixLen)
@@ -136,7 +138,7 @@ public static int indexOfNonDigit(char[] chars, int offset)
{
for (int i = offset; i < chars.length; i++)
{
- if (!isDigit(chars[i]))
+ if (isNotDigit(chars[i]))
{
return i;
}
@@ -144,9 +146,9 @@ public static int indexOfNonDigit(char[] chars, int offset)
return -1;
}
- private static boolean isDigit(char c)
+ private static boolean isNotDigit(char c)
{
- return (c >= ZERO && c <= '9');
+ return (c < ZERO || c > '9');
}
private static int digit(char c)
diff --git a/src/test/java/com/ethlo/time/AbstractTest.java b/src/test/java/com/ethlo/time/AbstractTest.java
index 47992f7..688282c 100644
--- a/src/test/java/com/ethlo/time/AbstractTest.java
+++ b/src/test/java/com/ethlo/time/AbstractTest.java
@@ -22,12 +22,15 @@
import org.junit.jupiter.api.BeforeEach;
+import java.text.DecimalFormat;
+
public abstract class AbstractTest
{
protected Rfc3339Parser parser;
protected Rfc3339Formatter formatter;
protected abstract Rfc3339Parser getParser();
+
protected abstract Rfc3339Formatter getFormatter();
protected abstract long getRuns();
@@ -45,18 +48,27 @@ protected final void unsupported(final Chronograph chronograph, String msg)
});
}
- protected final void perform(final Chronograph chronograph, final Runnable func, final String msg)
+ protected final void perform(final Runnable func, final String msg)
{
// Warm-up
- for (int i = 0; i < getRuns(); i++)
+ for (int i = 0; i < getRuns() * 2; i++)
{
func.run();
}
// Benchmark
- for (int i = 0; i < getRuns(); i++)
+ final Chronograph c = Chronograph.create();
+ c.timed(msg, () ->
{
- chronograph.timed(msg, func);
- }
+ for (int i = 0; i < getRuns(); i++)
+ {
+ func.run();
+ }
+ });
+ System.out.println(c.prettyPrint());
+
+ final double ns = c.getTotalTime().toNanos();
+ System.out.printf("%s - %.2f nanoseconds per operation%n", msg, (ns / getRuns()));
+ System.out.printf("%s - %s operations per second%n", msg, new DecimalFormat("###,###,###").format(getRuns() * 1_000_000_000 / ns));
}
}
diff --git a/src/test/java/com/ethlo/time/BenchmarkTest.java b/src/test/java/com/ethlo/time/BenchmarkTest.java
index 8ac4c85..2b459cf 100644
--- a/src/test/java/com/ethlo/time/BenchmarkTest.java
+++ b/src/test/java/com/ethlo/time/BenchmarkTest.java
@@ -20,14 +20,9 @@
* #L%
*/
-import static org.assertj.core.api.Assertions.assertThat;
-
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.Map;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
@@ -35,37 +30,24 @@
public abstract class BenchmarkTest extends AbstractTest
{
private final OffsetDateTime d = OffsetDateTime.of(2017, 12, 21, 15, 27, 39, 987, ZoneOffset.UTC);
-
- private static final Chronograph chronograph = Chronograph.create(CaptureConfig.minInterval(Duration.ofMillis(1)));
+ private static final Chronograph chronograph = Chronograph.create(CaptureConfig.minInterval(Duration.ofMillis(25)));
@Override
protected long getRuns()
{
- return 1_000_000;
+ return 10_000_000;
}
@Test
public void testParsePerformance()
{
- final Map formats = new LinkedHashMap<>();
- for (String f : Arrays.asList(
- "2017-12-21T15:27:39.987Z",
- "2017-12-21T15:27:39.98Z",
- "2017-12-21T15:27:39.9Z",
- "2017-12-21T15:27:39Z"
- ))
- {
- formats.put(f, OffsetDateTime.parse(f));
- }
-
final String name = parser.getClass().getSimpleName() + " - parse";
- perform(chronograph, () ->
- {
- for (Map.Entry e : formats.entrySet())
- {
- assertThat(parser.parseDateTime(e.getKey())).isEqualTo(e.getValue());
- }
- }, name);
+ perform(() -> parser.parseDateTime("2017-12-21T12:20:45.987Z"), name);
+ }
+
+ protected Chronograph getChronograph()
+ {
+ return chronograph;
}
@Test
@@ -76,11 +58,11 @@ public void testParseLenient()
if (parser instanceof W3cDateTimeUtil)
{
final W3cDateTimeUtil w3cUtil = (W3cDateTimeUtil) parser;
- perform(chronograph, () -> w3cUtil.parseLenient(s), name);
+ perform(() -> w3cUtil.parseLenient(s), name);
}
else
{
- unsupported(chronograph, name);
+ unsupported(getChronograph(), name);
}
}
@@ -90,17 +72,17 @@ public void testFormatPerformance()
final String name = parser.getClass().getSimpleName() + " - formatUtc";
if (formatter != null)
{
- perform(chronograph, () -> formatter.formatUtc(d), name);
+ perform(() -> formatter.formatUtc(d), name);
}
else
{
- unsupported(chronograph, name);
+ unsupported(getChronograph(), name);
}
}
@AfterAll
static void printStats()
{
- System.out.println(chronograph.prettyPrint());
+// System.out.println(Report.prettyPrint(getChronograph().getTaskData(), OutputConfig.EXTENDED.percentiles(90, 95, 99, 99.5), TableTheme.RED_HERRING));
}
}
diff --git a/src/test/java/com/ethlo/time/CorrectnessTest.java b/src/test/java/com/ethlo/time/CorrectnessTest.java
index 2b8cf0c..e9b67f6 100644
--- a/src/test/java/com/ethlo/time/CorrectnessTest.java
+++ b/src/test/java/com/ethlo/time/CorrectnessTest.java
@@ -215,17 +215,13 @@ public void testFormat5()
@Test
public void testParseEmptyString()
{
- final String s = "";
- final OffsetDateTime date = parser.parseDateTime(s);
- assertThat(date).isNull();
+ assertThrows(DateTimeException.class, () -> parser.parseDateTime(""));
}
@Test
public void testParseNull()
{
- final String s = null;
- final OffsetDateTime date = parser.parseDateTime(s);
- assertThat(date).isNull();
+ assertThrows(NullPointerException.class, () -> parser.parseDateTime(null));
}
@Test
diff --git a/src/test/java/com/ethlo/time/EthloITUBenchmarkTest.java b/src/test/java/com/ethlo/time/EthloITUBenchmarkTest.java
index a336ebe..917cc39 100644
--- a/src/test/java/com/ethlo/time/EthloITUBenchmarkTest.java
+++ b/src/test/java/com/ethlo/time/EthloITUBenchmarkTest.java
@@ -33,4 +33,16 @@ protected Rfc3339Formatter getFormatter()
{
return new EthloITU();
}
+
+ @Override
+ protected Chronograph getChronograph()
+ {
+ return null;
+ }
+
+ @Override
+ protected long getRuns()
+ {
+ return 100_000_000;
+ }
}
diff --git a/src/test/java/com/ethlo/time/W3cCorrectnessTest.java b/src/test/java/com/ethlo/time/W3cCorrectnessTest.java
index 4fc6280..d0dfebf 100644
--- a/src/test/java/com/ethlo/time/W3cCorrectnessTest.java
+++ b/src/test/java/com/ethlo/time/W3cCorrectnessTest.java
@@ -21,6 +21,7 @@
*/
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import java.time.DateTimeException;
import java.time.LocalDate;
@@ -44,9 +45,7 @@ public class W3cCorrectnessTest extends AbstractTest
@Test
public void testParseEmptyString()
{
- final String s = "";
- final OffsetDateTime date = parser.parseDateTime(s);
- assertThat(date).isNull();
+ assertThrows(DateTimeException.class, () -> parser.parseDateTime(""));
}
@Test
@@ -119,9 +118,7 @@ public void testParseBestEffort1DigitMinute()
@Test
public void testParseNull()
{
- final String s = null;
- final OffsetDateTime date = parser.parseDateTime(s);
- assertThat(date).isNull();
+ assertThrows(NullPointerException.class, () -> parser.parseDateTime(null));
}
@Override