diff --git a/src/main/java/com/ethlo/time/DateTime.java b/src/main/java/com/ethlo/time/DateTime.java index b177611..89555c3 100644 --- a/src/main/java/com/ethlo/time/DateTime.java +++ b/src/main/java/com/ethlo/time/DateTime.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,12 +31,13 @@ import java.time.OffsetDateTime; import java.time.Year; import java.time.YearMonth; +import java.util.Objects; import java.util.Optional; import com.ethlo.time.internal.LimitedCharArrayIntegerUtil; /** - * Container class for parsed date/date-time data. The {@link #getField()} contains the highest granularity field found, like MONTH, MINUTE, SECOND. + * Container class for parsed date/date-time data. The {@link #getMostGranularField()} contains the highest granularity field found, like MONTH, MINUTE, SECOND. */ public class DateTime { @@ -63,36 +64,60 @@ public DateTime(final Field field, final int year, final int month, final int da this.offset = offset; } + /** + * Create a new instance with second granularity from the input parameters + */ public static DateTime of(int year, int month, int day, int hour, int minute, int second, TimezoneOffset offset) { return new DateTime(Field.SECOND, year, month, day, hour, minute, second, 0, offset); } + /** + * Create a new instance with nanosecond granularity from the input parameters + */ public static DateTime of(int year, int month, int day, int hour, int minute, int second, int nanos, TimezoneOffset offset) { return new DateTime(Field.NANO, year, month, day, hour, minute, second, nanos, offset); } + /** + * Create a new instance with year granularity from the input parameters + */ public static DateTime ofYear(int year) { return new DateTime(Field.YEAR, year, 0, 0, 0, 0, 0, 0, null); } + /** + * Create a new instance with year-month granularity from the input parameters + */ public static DateTime ofYearMonth(int years, int months) { return new DateTime(Field.MONTH, years, months, 0, 0, 0, 0, 0, null); } + /** + * Create a new instance with day granularity from the input parameters + */ public static DateTime ofDate(int years, int months, int days) { return new DateTime(Field.DAY, years, months, days, 0, 0, 0, 0, null); } + /** + * Create a new instance with minute granularity from the input parameters + */ public static DateTime of(int years, int months, int days, int hours, int minute, TimezoneOffset offset) { return new DateTime(Field.MINUTE, years, months, days, hours, minute, 0, 0, offset); } + /** + * Create a new instance with data from the specified date-time. + * + * @param dateTime The date-time to copy data from + * @return A new instance + */ public static DateTime of(OffsetDateTime dateTime) { return DateTime.of(dateTime.getYear(), dateTime.getMonthValue(), dateTime.getDayOfMonth(), dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond(), dateTime.getNano(), TimezoneOffset.of(dateTime.getOffset())); @@ -164,7 +189,7 @@ public Optional getOffset() } /** - * Creates a {@link Year} discarding any higher resolution fields + * Creates a {@link Year} discarding any higher granularity fields * * @return the {@link Year} */ @@ -174,7 +199,7 @@ public Year toYear() } /** - * Creates a {@link YearMonth} discarding any higher resolution fields + * Creates a {@link YearMonth} discarding any higher granularity fields * * @return the {@link YearMonth} */ @@ -205,13 +230,13 @@ public OffsetDateTime toOffsetDatetime() assertMinGranularity(Field.MINUTE); if (offset != null) { - return OffsetDateTime.of(year, month, day, hour, minute, second, nano, offset.asJavaTimeOffset()); + return OffsetDateTime.of(year, month, day, hour, minute, second, nano, offset.toZoneOffset()); } throw new DateTimeException("No zone offset information found"); } /** - * Creates a {@link LocalDate}, discarding any higher resolution fields + * Creates a {@link LocalDate}, discarding any higher granularity fields * * @return the {@link LocalDate} */ @@ -222,29 +247,40 @@ public LocalDate toLocalDate() } /** - * Returns the minimum field found during parsing + * Returns the most granular field found during parsing * - * @return The minimum field found + * @return The field found */ - public Field getField() + public Field getMostGranularField() { return field; } - public DateTime assertMinGranularity(Field field) + private void assertMinGranularity(Field field) { if (!includesGranularity(field)) { throw new DateTimeException("No " + field.name() + " field found"); } - return this; } + /** + * Formats this date-time as an ISO formatted string with the last included field as specified. + * + * @param lastIncluded The last specified field to include + * @return The formatted date/date-time string + */ public String toString(final Field lastIncluded) { return toString(this, lastIncluded, 0); } + /** + * Formats this date-time as an RFC-3339 compatible string with the specified number of fractions in the second. + * + * @param fractionDigits The number of fractions to include + * @return The formatted date/date-time string + */ public String toString(final int fractionDigits) { return toString(this, Field.NANO, fractionDigits); @@ -252,9 +288,9 @@ public String toString(final int fractionDigits) private String toString(final DateTime date, final Field lastIncluded, final int fractionDigits) { - if (lastIncluded.ordinal() > date.getField().ordinal()) + if (lastIncluded.ordinal() > date.getMostGranularField().ordinal()) { - throw new DateTimeException("Requested granularity was " + lastIncluded.name() + ", but contains only granularity " + date.getField().name()); + throw new DateTimeException("Requested granularity was " + lastIncluded.name() + ", but contains only granularity " + date.getMostGranularField().name()); } final TimezoneOffset tz = date.getOffset().orElse(null); final char[] buffer = new char[35]; @@ -330,9 +366,49 @@ private String toString(final DateTime date, final Field lastIncluded, final int return finish(buffer, 20 + fractionDigits, tz); } + /** + * Formats this date-time as a date/date-time with the same fields as was parsed and no fractions in the second. + * + * @return The formatted date/date-time string + */ @Override public String toString() { return toString(field); } + + /** + * * @hidden + */ + @Override + public boolean equals(final Object o) + { + if (this == o) + { + return true; + } + if (o == null || getClass() != o.getClass()) + { + return false; + } + DateTime dateTime = (DateTime) o; + return year == dateTime.year + && month == dateTime.month + && day == dateTime.day + && hour == dateTime.hour + && minute == dateTime.minute + && second == dateTime.second + && nano == dateTime.nano + && field == dateTime.field + && Objects.equals(offset, dateTime.offset); + } + + /** + * @hidden + */ + @Override + public int hashCode() + { + return Objects.hash(field.ordinal(), year, month, day, hour, minute, second, nano, offset); + } } diff --git a/src/main/java/com/ethlo/time/ITU.java b/src/main/java/com/ethlo/time/ITU.java index 3ad85b7..c9157ab 100644 --- a/src/main/java/com/ethlo/time/ITU.java +++ b/src/main/java/com/ethlo/time/ITU.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2018 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import com.ethlo.time.internal.EthloITU; /** - * The main class for accessing the functions in this library + * The main access to the parse and formatting functions in this library. */ public class ITU { @@ -86,40 +86,98 @@ public static boolean isValid(String text) * Format the input as an RFC-3339 formatted date-time in the UTC timezone * * @param offsetDateTime The date-time to format - * @param fractionDigits The Nuber of fraction digits in the second - * @return A formatted string + * @param fractionDigits The number of fraction digits in the second field + * @return The formatted string */ public static String formatUtc(OffsetDateTime offsetDateTime, int fractionDigits) { return delegate.formatUtc(offsetDateTime, fractionDigits); } - public static String formatUtc(OffsetDateTime date, Field lastIncluded) + /** + * Format the input as an ISO format string, limited to the granularity of the specified field, in the UTC timezone. + * @param offsetDateTime The date-time to format + * @param lastIncluded The last included field + * @return The formatted string + */ + public static String formatUtc(OffsetDateTime offsetDateTime, Field lastIncluded) { - return delegate.formatUtc(date, lastIncluded); + return delegate.formatUtc(offsetDateTime, lastIncluded); } - public static String formatUtc(OffsetDateTime date) + /** + * Format the input as an RFC-3339 formatted date-time in the timezone of the input. + * + * @param offsetDateTime The date-time to format + * @return The formatted string + */ + public static String format(OffsetDateTime offsetDateTime) { - return delegate.formatUtc(date); + return delegate.format(offsetDateTime, offsetDateTime.getOffset(), 0); } - public static String formatUtcMilli(OffsetDateTime date) + /** + * Format the input as an RFC-3339 formatted date-time in the timezone of the input, with the specified number of fraction digits. + * + * @param offsetDateTime The date-time to format + * @param fractionDigits The number of fraction digits in the second field + * @return The formatted string + */ + public static String format(OffsetDateTime offsetDateTime, int fractionDigits) { - return delegate.formatUtcMilli(date); + return delegate.format(offsetDateTime, offsetDateTime.getOffset(), fractionDigits); } - public static String formatUtcMicro(OffsetDateTime date) + /** + * Format the input as an RFC-3339 formatted date-time in the UTC timezone with second resolution. + * + * @param offsetDateTime The date-time to format. + * @return The formatted string with second resolution. + */ + public static String formatUtc(OffsetDateTime offsetDateTime) { - return delegate.formatUtcMicro(date); + return delegate.formatUtc(offsetDateTime); } - public static String formatUtcNano(OffsetDateTime date) + /** + * Format the input as an RFC-3339 formatted date-time in the UTC timezone with millisecond resolution. + * + * @param offsetDateTime The date-time to format. + * @return The formatted string with millisecond resolution. + */ + public static String formatUtcMilli(final OffsetDateTime offsetDateTime) { - return delegate.formatUtcNano(date); + return delegate.formatUtcMilli(offsetDateTime); } - public static void parse(String text, TemporalConsumer temporalConsumer) + /** + * Format the input as an RFC-3339 formatted date-time in the UTC timezone with microsecond resolution. + * + * @param offsetDateTime The date-time to format + * @return The formatted string with microsecond resolution + */ + public static String formatUtcMicro(final OffsetDateTime offsetDateTime) + { + return delegate.formatUtcMicro(offsetDateTime); + } + + /** + * Format the input as an RFC-3339 formatted date-time in the UTC timezone with nanosecond resolution + * + * @param offsetDateTime The date-time to format + * @return The formatted string with nanosecond resolution + */ + public static String formatUtcNano(final OffsetDateTime offsetDateTime) + { + return delegate.formatUtcNano(offsetDateTime); + } + + /** + * Parse the input, and use callbacks for the type of date/date-time it contains. This allows you to handle different granularity inputs with ease! + * @param text The text to parse as a date/date-time + * @param temporalConsumer The consumer of the found date/date-time + */ + public static void parse(final String text, final TemporalConsumer temporalConsumer) { final DateTime dateTime = delegate.parse(text); if (dateTime.includesGranularity(Field.MINUTE)) @@ -147,6 +205,12 @@ else if (dateTime.includesGranularity(Field.MONTH)) } } + /** + * Parse the input, and use callbacks for the type of date/date-time it contains. This allows you to handle different granularity inputs with ease! + * @param text The text to parse as a date/date-time + * @param temporalHandler The handler of the found date/date-time + */ + public static T parse(String text, TemporalHandler temporalHandler) { final DateTime dateTime = delegate.parse(text); @@ -175,6 +239,12 @@ else if (dateTime.includesGranularity(Field.MONTH)) } } + /** + * Check if the input is valid for one of the specified types + * @param text The input to check + * @param types The types that are considered valid + * @return True if valid, otherwise false + */ public static boolean isValid(final String text, TemporalType... types) { try diff --git a/src/main/java/com/ethlo/time/LeapSecondException.java b/src/main/java/com/ethlo/time/LeapSecondException.java index a85f799..4b32b2c 100644 --- a/src/main/java/com/ethlo/time/LeapSecondException.java +++ b/src/main/java/com/ethlo/time/LeapSecondException.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2019 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/TemporalConsumer.java b/src/main/java/com/ethlo/time/TemporalConsumer.java index 004e125..6c961f9 100644 --- a/src/main/java/com/ethlo/time/TemporalConsumer.java +++ b/src/main/java/com/ethlo/time/TemporalConsumer.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/TemporalHandler.java b/src/main/java/com/ethlo/time/TemporalHandler.java index 47d3df9..c26fe11 100644 --- a/src/main/java/com/ethlo/time/TemporalHandler.java +++ b/src/main/java/com/ethlo/time/TemporalHandler.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/TemporalType.java b/src/main/java/com/ethlo/time/TemporalType.java index f5125fa..105d172 100644 --- a/src/main/java/com/ethlo/time/TemporalType.java +++ b/src/main/java/com/ethlo/time/TemporalType.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/TimezoneOffset.java b/src/main/java/com/ethlo/time/TimezoneOffset.java index e25ad53..679a042 100644 --- a/src/main/java/com/ethlo/time/TimezoneOffset.java +++ b/src/main/java/com/ethlo/time/TimezoneOffset.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -77,7 +77,7 @@ public int getTotalSeconds() return hours * 60 * 60 + minutes * 60; } - public ZoneOffset asJavaTimeOffset() + public ZoneOffset toZoneOffset() { if (this.equals(UTC)) { diff --git a/src/main/java/com/ethlo/time/internal/DefaultLeapSecondHandler.java b/src/main/java/com/ethlo/time/internal/DefaultLeapSecondHandler.java index 9dcac61..44cdbe5 100644 --- a/src/main/java/com/ethlo/time/internal/DefaultLeapSecondHandler.java +++ b/src/main/java/com/ethlo/time/internal/DefaultLeapSecondHandler.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/internal/EthloITU.java b/src/main/java/com/ethlo/time/internal/EthloITU.java index 4e0daa9..eb5785a 100644 --- a/src/main/java/com/ethlo/time/internal/EthloITU.java +++ b/src/main/java/com/ethlo/time/internal/EthloITU.java @@ -159,6 +159,7 @@ private TimezoneOffset parseTimezone(char[] chars, int offset) if (sign == MINUS) { hours = -hours; + minutes = -minutes; } else if (sign != PLUS) { @@ -184,41 +185,47 @@ private void assertNoMoreChars(char[] chars, int lastUsed) @Override public String formatUtc(OffsetDateTime date, int fractionDigits) { - return doFormatUtc(date, Field.SECOND, fractionDigits); + return doFormat(date, ZoneOffset.UTC, Field.SECOND, fractionDigits); } @Override public String formatUtc(OffsetDateTime date, Field lastIncluded) { - return doFormatUtc(date, lastIncluded, 0); + return doFormat(date, ZoneOffset.UTC, lastIncluded, 0); } - private String doFormatUtc(OffsetDateTime date, Field lastIncluded, int fractionDigits) + @Override + public String format(OffsetDateTime date, ZoneOffset adjustTo, final int fractionDigits) + { + return doFormat(date, adjustTo, Field.NANO, fractionDigits); + } + + private String doFormat(OffsetDateTime date, ZoneOffset adjustTo, Field lastIncluded, int fractionDigits) { assertMaxFractionDigits(fractionDigits); - OffsetDateTime utc = date; - if (date.getOffset() != ZoneOffset.UTC) + OffsetDateTime adjusted = date; + if (!date.getOffset().equals(adjustTo)) { - utc = date.atZoneSameInstant(FastUTCZoneId.get()).toOffsetDateTime(); + adjusted = date.atZoneSameInstant(adjustTo).toOffsetDateTime(); } - final TimezoneOffset tz = TimezoneOffset.UTC; + final TimezoneOffset tz = TimezoneOffset.of(adjustTo); final char[] buffer = new char[31]; - if (handleDatePart(lastIncluded, buffer, utc.getYear(), 0, 4, Field.YEAR)) + if (handleDatePart(lastIncluded, buffer, adjusted.getYear(), 0, 4, Field.YEAR)) { return finish(buffer, Field.YEAR.getRequiredLength(), null); } buffer[4] = DATE_SEPARATOR; - if (handleDatePart(lastIncluded, buffer, utc.getMonthValue(), 5, 2, Field.MONTH)) + if (handleDatePart(lastIncluded, buffer, adjusted.getMonthValue(), 5, 2, Field.MONTH)) { return finish(buffer, Field.MONTH.getRequiredLength(), null); } buffer[7] = DATE_SEPARATOR; - if (handleDatePart(lastIncluded, buffer, utc.getDayOfMonth(), 8, 2, Field.DAY)) + if (handleDatePart(lastIncluded, buffer, adjusted.getDayOfMonth(), 8, 2, Field.DAY)) { return finish(buffer, Field.DAY.getRequiredLength(), null); } @@ -227,21 +234,21 @@ private String doFormatUtc(OffsetDateTime date, Field lastIncluded, int fraction buffer[10] = SEPARATOR_UPPER; // Time - LimitedCharArrayIntegerUtil.toString(utc.getHour(), buffer, 11, 2); + LimitedCharArrayIntegerUtil.toString(adjusted.getHour(), buffer, 11, 2); buffer[13] = TIME_SEPARATOR; - if (handleDatePart(lastIncluded, buffer, utc.getMinute(), 14, 2, Field.MINUTE)) + if (handleDatePart(lastIncluded, buffer, adjusted.getMinute(), 14, 2, Field.MINUTE)) { return finish(buffer, Field.MINUTE.getRequiredLength(), tz); } buffer[16] = TIME_SEPARATOR; - LimitedCharArrayIntegerUtil.toString(utc.getSecond(), buffer, 17, 2); + LimitedCharArrayIntegerUtil.toString(adjusted.getSecond(), buffer, 17, 2); // Second fractions final boolean hasFractionDigits = fractionDigits > 0; if (hasFractionDigits) { buffer[19] = FRACTION_SEPARATOR; - addFractions(buffer, fractionDigits, utc.getNano()); + addFractions(buffer, fractionDigits, adjusted.getNano()); return finish(buffer, 20 + fractionDigits, tz); } return finish(buffer, 19, tz); @@ -273,9 +280,9 @@ private static int writeTz(char[] buf, int start, TimezoneOffset tz) else { buf[start] = tz.getTotalSeconds() < 0 ? MINUS : PLUS; - LimitedCharArrayIntegerUtil.toString(tz.getHours(), buf, start + 1, 2); + LimitedCharArrayIntegerUtil.toString(Math.abs(tz.getHours()), buf, start + 1, 2); buf[start + 3] = TIME_SEPARATOR; - LimitedCharArrayIntegerUtil.toString(tz.getMinutes(), buf, start + 4, 2); + LimitedCharArrayIntegerUtil.toString(Math.abs(tz.getMinutes()), buf, start + 4, 2); return 6; } } @@ -289,9 +296,19 @@ private void addFractions(char[] buf, int fractionDigits, int nano) @Override public OffsetDateTime parseDateTime(final String dateTime) { - return parse(dateTime).assertMinGranularity(Field.SECOND).toOffsetDatetime(); + return assertSecondsGranularity(parse(dateTime)).toOffsetDatetime(); + } + + private DateTime assertSecondsGranularity(DateTime dt) + { + if (!dt.includesGranularity(Field.SECOND)) + { + throw new DateTimeException("No " + Field.SECOND.name() + " field found"); + } + return dt; } + @Override public String formatUtcMilli(OffsetDateTime date) { @@ -444,7 +461,7 @@ private DateTime leapSecondCheck(int year, int month, int day, int hour, int min && utcMinute == 59) { // Consider it a leap second - final OffsetDateTime nearest = OffsetDateTime.of(year, month, day, hour, minute, 59, nanos, offset.asJavaTimeOffset()).plusSeconds(1); + final OffsetDateTime nearest = OffsetDateTime.of(year, month, day, hour, minute, 59, nanos, offset.toZoneOffset()).plusSeconds(1); throw new LeapSecondException(nearest, second, isValidLeapYearMonth); } } diff --git a/src/main/java/com/ethlo/time/internal/FastUTCZoneId.java b/src/main/java/com/ethlo/time/internal/FastUTCZoneId.java deleted file mode 100644 index d12d849..0000000 --- a/src/main/java/com/ethlo/time/internal/FastUTCZoneId.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ethlo.time.internal; - -/*- - * #%L - * Internet Time Utility - * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) - * %% - * Licensed 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. - * #L% - */ - -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.zone.ZoneRules; -import java.time.zone.ZoneRulesProvider; -import java.util.Collections; -import java.util.NavigableMap; -import java.util.Set; - -public class FastUTCZoneId -{ - private static final String customZoneId = "ITU-UTC"; - private static final ZoneId delegate; - - static - { - // The heart of the magic: the ZoneRulesProvider - final ZoneRulesProvider customProvider = new ZoneRulesProvider() - { - @Override - protected Set provideZoneIds() - { - return Collections.singleton(customZoneId); - } - - @Override - protected NavigableMap provideVersions(String zoneId) - { - return Collections.emptyNavigableMap(); - } - - @Override - protected ZoneRules provideRules(String zoneId, boolean forCaching) - { - return ZoneOffset.UTC.getRules(); - } - }; - - // Registering the ZoneRulesProvider is the key to ZoneId using it - ZoneRulesProvider.registerProvider(customProvider); - delegate = ZoneId.of(customZoneId); - } - - public static ZoneId get() - { - return delegate; - } -} diff --git a/src/main/java/com/ethlo/time/internal/LeapSecondHandler.java b/src/main/java/com/ethlo/time/internal/LeapSecondHandler.java index 3b7fec0..168e7af 100644 --- a/src/main/java/com/ethlo/time/internal/LeapSecondHandler.java +++ b/src/main/java/com/ethlo/time/internal/LeapSecondHandler.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/internal/Rfc3339Formatter.java b/src/main/java/com/ethlo/time/internal/Rfc3339Formatter.java index a4dedfc..c360c51 100644 --- a/src/main/java/com/ethlo/time/internal/Rfc3339Formatter.java +++ b/src/main/java/com/ethlo/time/internal/Rfc3339Formatter.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/internal/Rfc3339Parser.java b/src/main/java/com/ethlo/time/internal/Rfc3339Parser.java index 29ea6a6..156e9eb 100644 --- a/src/main/java/com/ethlo/time/internal/Rfc3339Parser.java +++ b/src/main/java/com/ethlo/time/internal/Rfc3339Parser.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/com/ethlo/time/internal/W3cDateTimeUtil.java b/src/main/java/com/ethlo/time/internal/W3cDateTimeUtil.java index 4a8e3e8..7159fe0 100644 --- a/src/main/java/com/ethlo/time/internal/W3cDateTimeUtil.java +++ b/src/main/java/com/ethlo/time/internal/W3cDateTimeUtil.java @@ -21,6 +21,7 @@ */ import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.time.temporal.Temporal; import com.ethlo.time.DateTime; @@ -78,6 +79,8 @@ public interface W3cDateTimeUtil */ String formatUtc(OffsetDateTime date, int fractionDigits); + String format(OffsetDateTime date, ZoneOffset adjustTo, int fractionDigits); + /** * Parse the format and return it as a fitting sub-class of {@link Temporal} * diff --git a/src/test/java/com/ethlo/time/DateTimeTest.java b/src/test/java/com/ethlo/time/DateTimeTest.java new file mode 100644 index 0000000..e6771d9 --- /dev/null +++ b/src/test/java/com/ethlo/time/DateTimeTest.java @@ -0,0 +1,58 @@ +package com.ethlo.time; + +/*- + * #%L + * Internet Time Utility + * %% + * Copyright (C) 2017 Morten Haraldsen (ethlo) + * %% + * Licensed 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. + * #L% + */ + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.Year; +import java.time.YearMonth; +import java.time.temporal.Temporal; + +import static org.assertj.core.api.Assertions.assertThat; + +@Tag("CorrectnessTest") +public class DateTimeTest +{ + final DateTime a = ITU.parseLenient("2018-01-06T23:59:12-04:30"); + final DateTime b = ITU.parseLenient("2018-01-06T23:59:12-04:30"); + final DateTime c = ITU.parseLenient("2018-01-06T23:59:12-05:30"); + + @Test + public void testEquals() + { + assertThat(a).isEqualTo(a); + assertThat(a).isEqualTo(b); + assertThat(b).isEqualTo(a); + assertThat(a).isNotEqualTo(c); + assertThat(a).isNotEqualTo(""); + } + + @Test + public void testHashcode() + { + System.out.println(a); + assertThat(a.hashCode()).isEqualTo(-148521044); + } +} diff --git a/src/test/java/com/ethlo/time/FieldTest.java b/src/test/java/com/ethlo/time/FieldTest.java index 33f72c4..9e98464 100644 --- a/src/test/java/com/ethlo/time/FieldTest.java +++ b/src/test/java/com/ethlo/time/FieldTest.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2019 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/com/ethlo/time/ITUTest.java b/src/test/java/com/ethlo/time/ITUTest.java index 24b6409..1295e4b 100644 --- a/src/test/java/com/ethlo/time/ITUTest.java +++ b/src/test/java/com/ethlo/time/ITUTest.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2019 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ import java.time.OffsetDateTime; import java.time.Year; import java.time.YearMonth; +import java.time.ZoneOffset; import java.time.temporal.Temporal; import org.junit.jupiter.api.Tag; @@ -81,6 +82,13 @@ void formatDateTimeWithFullGranularity() assertThat(DateTime.of(2012, 11, 31, 22, 50, 46, 123456789, TimezoneOffset.UTC).toString(9)).isEqualTo("2012-11-31T22:50:46.123456789Z"); } + @Test + void formatDateTimeWithSecondGranularity() + { + final OffsetDateTime input = OffsetDateTime.of(2012, 11, 30, 22, 50, 46, 123456789, ZoneOffset.ofHoursMinutes(-9, -30)); + assertThat(ITU.format(input)).isEqualTo("2012-11-30T22:50:46-09:30"); + } + @Test public void testFormatUtc() { diff --git a/src/test/java/com/ethlo/time/TemporalHandlerTest.java b/src/test/java/com/ethlo/time/TemporalHandlerTest.java index bb741d5..ff72751 100644 --- a/src/test/java/com/ethlo/time/TemporalHandlerTest.java +++ b/src/test/java/com/ethlo/time/TemporalHandlerTest.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/com/ethlo/time/TimezoneOffsetTest.java b/src/test/java/com/ethlo/time/TimezoneOffsetTest.java index 061c260..31d3977 100644 --- a/src/test/java/com/ethlo/time/TimezoneOffsetTest.java +++ b/src/test/java/com/ethlo/time/TimezoneOffsetTest.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,7 +60,7 @@ void getTotalSeconds() @Test void asJavaTimeOffset() { - assertThat(a.asJavaTimeOffset()).isEqualTo(ZoneOffset.ofHoursMinutes(10, 30)); + assertThat(a.toZoneOffset()).isEqualTo(ZoneOffset.ofHoursMinutes(10, 30)); } @Test diff --git a/src/test/java/com/ethlo/time/W3cCorrectnessTest.java b/src/test/java/com/ethlo/time/W3cCorrectnessTest.java index 2f82276..0704350 100644 --- a/src/test/java/com/ethlo/time/W3cCorrectnessTest.java +++ b/src/test/java/com/ethlo/time/W3cCorrectnessTest.java @@ -74,7 +74,7 @@ public void testParseYear() { final DateTime date = w3cDateUtil.parse("2012"); assertThat(date.getYear()).isEqualTo(2012); - assertThat(date.getField()).isEqualTo(Field.YEAR); + assertThat(date.getMostGranularField()).isEqualTo(Field.YEAR); assertThat(date.toYear()).isEqualTo(Year.of(2012)); } @@ -84,7 +84,7 @@ public void testParseYearMonth() final DateTime date = w3cDateUtil.parse("2012-10"); assertThat(date.getYear()).isEqualTo(2012); assertThat(date.getMonth()).isEqualTo(10); - assertThat(date.getField()).isEqualTo(Field.MONTH); + assertThat(date.getMostGranularField()).isEqualTo(Field.MONTH); final YearMonth yearMonth = w3cDateUtil.parse("2012-10").toYearMonth(); assertThat(yearMonth.getYear()).isEqualTo(2012); assertThat(yearMonth.getMonthValue()).isEqualTo(10); @@ -100,7 +100,7 @@ public void testParseDate() assertThat(date.getYear()).isEqualTo(2012); assertThat(date.getMonth()).isEqualTo(3); assertThat(date.getDayOfMonth()).isEqualTo(29); - assertThat(date.getField()).isEqualTo(Field.DAY); + assertThat(date.getMostGranularField()).isEqualTo(Field.DAY); assertThat(date.toString()).isEqualTo(input); } @@ -116,7 +116,7 @@ public void testParseDateTimeNanos() assertThat(date.getMinute()).isEqualTo(22); assertThat(date.getSecond()).isEqualTo(39); assertThat(date.getNano()).isEqualTo(123456789); - assertThat(date.getField()).isEqualTo(Field.NANO); + assertThat(date.getMostGranularField()).isEqualTo(Field.NANO); assertThat(date.getOffset()).isPresent(); assertThat(date.getOffset().get().getHours()).isEqualTo(13); assertThat(date.getOffset().get().getMinutes()).isEqualTo(30); @@ -135,7 +135,7 @@ public void testParseDateTimeWithoutFractions() assertThat(date.getMinute()).isEqualTo(22); assertThat(date.getSecond()).isEqualTo(39); assertThat(date.getNano()).isEqualTo(0); - assertThat(date.getField()).isEqualTo(Field.SECOND); + assertThat(date.getMostGranularField()).isEqualTo(Field.SECOND); assertThat(date.getOffset()).isPresent(); assertThat(date.getOffset().get().getHours()).isEqualTo(13); assertThat(date.getOffset().get().getMinutes()).isEqualTo(30); @@ -175,7 +175,7 @@ public void testParseDateTimeWithoutSeconds() assertThat(date.getDayOfMonth()).isEqualTo(27); assertThat(date.getHour()).isEqualTo(17); assertThat(date.getMinute()).isEqualTo(22); - assertThat(date.getField()).isEqualTo(Field.MINUTE); + assertThat(date.getMostGranularField()).isEqualTo(Field.MINUTE); assertThat(date.getOffset()).hasValue(TimezoneOffset.UTC); } @@ -188,7 +188,7 @@ public void testParseDateTimeWithoutSecondsAndTimezone() assertThat(date.getDayOfMonth()).isEqualTo(27); assertThat(date.getHour()).isEqualTo(17); assertThat(date.getMinute()).isEqualTo(22); - assertThat(date.getField()).isEqualTo(Field.MINUTE); + assertThat(date.getMostGranularField()).isEqualTo(Field.MINUTE); assertThat(date.getOffset()).isEmpty(); final DateTimeException excOffsetDateTime = assertThrows(DateTimeException.class, date::toOffsetDatetime); @@ -212,7 +212,7 @@ public void testParseDateTimeNoOffsetToLocalDateTime() assertThat(date.getHour()).isEqualTo(17); assertThat(date.getMinute()).isEqualTo(22); assertThat(date.getSecond()).isEqualTo(39); - assertThat(date.getField()).isEqualTo(Field.SECOND); + assertThat(date.getMostGranularField()).isEqualTo(Field.SECOND); assertThat(date.getOffset()).isEmpty(); final LocalDateTime localDateTime = date.toLocalDatetime(); assertThat(localDateTime.getYear()).isEqualTo(2012); diff --git a/src/test/java/com/ethlo/time/itu/EthloItuProfilerTest.java b/src/test/java/com/ethlo/time/itu/EthloItuProfilerTest.java index 9066150..45ef5a9 100644 --- a/src/test/java/com/ethlo/time/itu/EthloItuProfilerTest.java +++ b/src/test/java/com/ethlo/time/itu/EthloItuProfilerTest.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/com/ethlo/time/itu/ITULenientParserBenchmarkTest.java b/src/test/java/com/ethlo/time/itu/ITULenientParserBenchmarkTest.java index 35b2779..2217347 100644 --- a/src/test/java/com/ethlo/time/itu/ITULenientParserBenchmarkTest.java +++ b/src/test/java/com/ethlo/time/itu/ITULenientParserBenchmarkTest.java @@ -4,7 +4,7 @@ * #%L * Internet Time Utility * %% - * Copyright (C) 2017 - 2022 Morten Haraldsen (ethlo) + * Copyright (C) 2017 Morten Haraldsen (ethlo) * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.