Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/test/java/com/ethlo/time/StdJdkCorrectnessTest.java
  • Loading branch information
ethlo committed Aug 12, 2019
2 parents 3072718 + 6f2513e commit 61b7260
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 66 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,14 @@ Your milage may vary. The tests are included in this repository.

## Example use
```java
final FastInternetDateTimeUtil itu = new FastInternetDateTimeUtil();
final String s = "2012-12-27T19:07:22.123456789-03:00";

// Parse a string
final OffsetDateTime dateTime = itu.parse(s);
final OffsetDateTime dateTime = ITU.parseDateTime("2012-12-27T19:07:22.123456789-03:00");

// Format with no fraction digits
final String formatted = itu.formatUtc(dateTime); // 2012-12-27T22:07:22Z
final String formatted = ITU.formatUtc(dateTime); // 2012-12-27T22:07:22Z

// Format with microsecond precision
final String formattedMicro = itu.formatUtcMicro(dateTime); // 2012-12-27T22:07:22.123457Z
final String formattedMicro = ITU.formatUtcMicro(dateTime); // 2012-12-27T22:07:22.123457Z
```
## Q & A

Expand Down Expand Up @@ -84,10 +81,17 @@ Typical formats include:

## Limitations

### Local offset
For the sake of avoiding data integrity issues, this library will not allow offset of `-00:00`.
Such offset is described in RFC3339 section 4.3., named "Unknown Local Offset Convention". Such offset is explicitly prohibited in ISO-8601 as well.

> If the time in UTC is known, but the offset to local time is unknown,
this can be represented with an offset of "-00:00". This differs
semantically from an offset of "Z" or "+00:00", which imply that UTC
is the preferred reference point for the specified time.

### Leap second parsing
Since Java's `java.time` classes do not support storing leap seconds, it is not obvious how to support this.

ITU will parse the date-time correctly, however storing such values is not possible (in a `java.time.OffsetDateTime`), the `60` is therefore abandoned and the date-time will use `59` instead of `60`.

18 changes: 16 additions & 2 deletions src/main/java/com/ethlo/time/FastInternetDateTimeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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;
Expand All @@ -33,8 +34,7 @@

public class FastInternetDateTimeUtil extends AbstractRfc3339 implements W3cDateTimeUtil
{
private final StdJdkInternetDateTimeUtil delegate = new StdJdkInternetDateTimeUtil();

public static final int LEAP_SECOND_SECONDS = 60;
private static final char PLUS = '+';
private static final char MINUS = '-';
private static final char DATE_SEPARATOR = '-';
Expand All @@ -46,6 +46,7 @@ public class FastInternetDateTimeUtil extends AbstractRfc3339 implements W3cDate
private static final char ZULU_UPPER = 'Z';
private static final char ZULU_LOWER = 'z';
private static final int[] widths = new int[]{100_000_000, 10_000_000, 1_000_000, 100_000, 10_000, 1_000, 100, 10, 1};
private final StdJdkInternetDateTimeUtil delegate = new StdJdkInternetDateTimeUtil();

@Override
public OffsetDateTime parseDateTime(String s)
Expand Down Expand Up @@ -402,6 +403,19 @@ else if (remaining == 0)
throw new DateTimeException("Unexpected character at position 19:" + chars[19]);
}

if (second == LEAP_SECOND_SECONDS)
{
// Do not fall over trying to parse leap seconds
final int utcHour = hour - (offset.getTotalSeconds() / 3_600);
final int utcMinute = minute - ((offset.getTotalSeconds() % 3_600) / 60);
if (((month == Month.DECEMBER.getValue() && day == 31) || (month == Month.JUNE.getValue() && day == 30))
&& utcHour == 23
&& utcMinute == 59)
{
// Consider it a leap second
throw new LeapSecondException(OffsetDateTime.of(year, month, day, hour, minute, 59, fractions, offset).plusSeconds(1), second);
}
}
return OffsetDateTime.of(year, month, day, hour, minute, second, fractions, offset);
}

Expand Down
45 changes: 45 additions & 0 deletions src/main/java/com/ethlo/time/LeapSecondException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.ethlo.time;

/*-
* #%L
* Internet Time Utility
* %%
* Copyright (C) 2017 - 2019 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.OffsetDateTime;

public class LeapSecondException extends RuntimeException
{
private final int secondsInMinute;
private final OffsetDateTime nearestDateTime;

public LeapSecondException(OffsetDateTime nearestDateTime, int secondsInMinute)
{
this.nearestDateTime = nearestDateTime;
this.secondsInMinute = secondsInMinute;
}

public int getSecondsInMinute()
{
return secondsInMinute;
}

public OffsetDateTime getNearestDateTime()
{
return nearestDateTime;
}
}
Loading

0 comments on commit 61b7260

Please sign in to comment.