diff --git a/src/main/java/com/ethlo/time/DateTime.java b/src/main/java/com/ethlo/time/DateTime.java index 7ba0118..b177611 100644 --- a/src/main/java/com/ethlo/time/DateTime.java +++ b/src/main/java/com/ethlo/time/DateTime.java @@ -256,14 +256,14 @@ private String toString(final DateTime date, final Field lastIncluded, final int { throw new DateTimeException("Requested granularity was " + lastIncluded.name() + ", but contains only granularity " + date.getField().name()); } - final boolean hasTz = date.getOffset().isPresent(); - final char[] buffer = new char[32]; + final TimezoneOffset tz = date.getOffset().orElse(null); + final char[] buffer = new char[35]; // YEAR LimitedCharArrayIntegerUtil.toString(date.getYear(), buffer, 0, 4); if (lastIncluded == Field.YEAR) { - return finish(buffer, Field.YEAR.getRequiredLength(), false); + return finish(buffer, Field.YEAR.getRequiredLength(), null); } // MONTH @@ -274,7 +274,7 @@ private String toString(final DateTime date, final Field lastIncluded, final int } if (lastIncluded == Field.MONTH) { - return finish(buffer, Field.MONTH.getRequiredLength(), false); + return finish(buffer, Field.MONTH.getRequiredLength(), null); } // DAY @@ -285,7 +285,7 @@ private String toString(final DateTime date, final Field lastIncluded, final int } if (lastIncluded == Field.DAY) { - return finish(buffer, Field.DAY.getRequiredLength(), false); + return finish(buffer, Field.DAY.getRequiredLength(), null); } // HOUR @@ -296,7 +296,7 @@ private String toString(final DateTime date, final Field lastIncluded, final int } if (lastIncluded == Field.HOUR) { - return finish(buffer, Field.HOUR.getRequiredLength(), hasTz); + return finish(buffer, Field.HOUR.getRequiredLength(), tz); } // MINUTE @@ -307,7 +307,7 @@ private String toString(final DateTime date, final Field lastIncluded, final int } if (lastIncluded == Field.MINUTE) { - return finish(buffer, Field.MINUTE.getRequiredLength(), hasTz); + return finish(buffer, Field.MINUTE.getRequiredLength(), tz); } // SECOND @@ -318,7 +318,7 @@ private String toString(final DateTime date, final Field lastIncluded, final int } if (lastIncluded == Field.SECOND) { - return finish(buffer, Field.SECOND.getRequiredLength(), hasTz); + return finish(buffer, Field.SECOND.getRequiredLength(), tz); } // Fractions @@ -327,7 +327,12 @@ private String toString(final DateTime date, final Field lastIncluded, final int buffer[19] = '.'; LimitedCharArrayIntegerUtil.toString(date.getNano(), buffer, 20, fractionDigits); } - return finish(buffer, 20 + fractionDigits, hasTz); + return finish(buffer, 20 + fractionDigits, tz); } + @Override + public String toString() + { + return toString(field); + } } diff --git a/src/main/java/com/ethlo/time/internal/EthloITU.java b/src/main/java/com/ethlo/time/internal/EthloITU.java index 59c08c1..4e0daa9 100644 --- a/src/main/java/com/ethlo/time/internal/EthloITU.java +++ b/src/main/java/com/ethlo/time/internal/EthloITU.java @@ -202,24 +202,25 @@ private String doFormatUtc(OffsetDateTime date, Field lastIncluded, int fraction { utc = date.atZoneSameInstant(FastUTCZoneId.get()).toOffsetDateTime(); } + final TimezoneOffset tz = TimezoneOffset.UTC; final char[] buffer = new char[31]; if (handleDatePart(lastIncluded, buffer, utc.getYear(), 0, 4, Field.YEAR)) { - return finish(buffer, Field.YEAR.getRequiredLength(), false); + return finish(buffer, Field.YEAR.getRequiredLength(), null); } buffer[4] = DATE_SEPARATOR; if (handleDatePart(lastIncluded, buffer, utc.getMonthValue(), 5, 2, Field.MONTH)) { - return finish(buffer, Field.MONTH.getRequiredLength(), false); + return finish(buffer, Field.MONTH.getRequiredLength(), null); } buffer[7] = DATE_SEPARATOR; if (handleDatePart(lastIncluded, buffer, utc.getDayOfMonth(), 8, 2, Field.DAY)) { - return finish(buffer, Field.DAY.getRequiredLength(), false); + return finish(buffer, Field.DAY.getRequiredLength(), null); } // T separator @@ -230,7 +231,7 @@ private String doFormatUtc(OffsetDateTime date, Field lastIncluded, int fraction buffer[13] = TIME_SEPARATOR; if (handleDatePart(lastIncluded, buffer, utc.getMinute(), 14, 2, Field.MINUTE)) { - return finish(buffer, Field.MINUTE.getRequiredLength(), true); + return finish(buffer, Field.MINUTE.getRequiredLength(), tz); } buffer[16] = TIME_SEPARATOR; LimitedCharArrayIntegerUtil.toString(utc.getSecond(), buffer, 17, 2); @@ -241,9 +242,9 @@ private String doFormatUtc(OffsetDateTime date, Field lastIncluded, int fraction { buffer[19] = FRACTION_SEPARATOR; addFractions(buffer, fractionDigits, utc.getNano()); - return finish(buffer, 20 + fractionDigits, true); + return finish(buffer, 20 + fractionDigits, tz); } - return finish(buffer, 19, true); + return finish(buffer, 19, tz); } private boolean handleDatePart(final Field lastIncluded, final char[] buffer, final int value, final int offset, final int length, final Field field) @@ -252,13 +253,31 @@ private boolean handleDatePart(final Field lastIncluded, final char[] buffer, fi return lastIncluded == field; } - public static String finish(char[] buf, int length, final boolean tz) + public static String finish(char[] buf, int length, final TimezoneOffset tz) { - if (tz) + int tzLen = 0; + if (tz != null) { - buf[length] = ZULU_UPPER; + tzLen = writeTz(buf, length, tz); + } + return new String(buf, 0, length + tzLen); + } + + private static int writeTz(char[] buf, int start, TimezoneOffset tz) + { + if (tz.equals(TimezoneOffset.UTC)) + { + buf[start] = ZULU_UPPER; + return 1; + } + else + { + buf[start] = tz.getTotalSeconds() < 0 ? MINUS : PLUS; + LimitedCharArrayIntegerUtil.toString(tz.getHours(), buf, start + 1, 2); + buf[start + 3] = TIME_SEPARATOR; + LimitedCharArrayIntegerUtil.toString(tz.getMinutes(), buf, start + 4, 2); + return 6; } - return new String(buf, 0, length + (tz ? 1 : 0)); } private void addFractions(char[] buf, int fractionDigits, int nano) diff --git a/src/test/java/com/ethlo/time/W3cCorrectnessTest.java b/src/test/java/com/ethlo/time/W3cCorrectnessTest.java index b880805..2f82276 100644 --- a/src/test/java/com/ethlo/time/W3cCorrectnessTest.java +++ b/src/test/java/com/ethlo/time/W3cCorrectnessTest.java @@ -95,17 +95,20 @@ public void testParseYearMonth() @Test public void testParseDate() { - final DateTime date = w3cDateUtil.parse("2012-03-29"); + final String input = "2012-03-29"; + final DateTime date = w3cDateUtil.parse(input); assertThat(date.getYear()).isEqualTo(2012); assertThat(date.getMonth()).isEqualTo(3); assertThat(date.getDayOfMonth()).isEqualTo(29); assertThat(date.getField()).isEqualTo(Field.DAY); + assertThat(date.toString()).isEqualTo(input); } @Test public void testParseDateTimeNanos() { - final DateTime date = w3cDateUtil.parse("2012-10-27T17:22:39.123456789+13:30"); + final String input = "2012-10-27T17:22:39.123456789+13:30"; + final DateTime date = w3cDateUtil.parse(input); assertThat(date.getYear()).isEqualTo(2012); assertThat(date.getMonth()).isEqualTo(10); assertThat(date.getDayOfMonth()).isEqualTo(27); @@ -118,6 +121,7 @@ public void testParseDateTimeNanos() assertThat(date.getOffset().get().getHours()).isEqualTo(13); assertThat(date.getOffset().get().getMinutes()).isEqualTo(30); assertThat(date.getOffset()).hasValue(TimezoneOffset.ofHoursMinutes(13, 30)); + assertThat(date.toString(9)).isEqualTo(input); } @Test