diff --git a/README.md b/README.md index a963bb79..e4fa1429 100644 --- a/README.md +++ b/README.md @@ -191,9 +191,9 @@ If you want to use [EventTime](https://github.com/fluent/fluentd/wiki/Forward-Pr ```java int epochSeconds; -int nanoSeconds; +int nanoseconds; : -EventTime eventTime = EventTime.fromEpoch(epochSeconds, nanoSeconds); +EventTime eventTime = EventTime.fromEpoch(epochSeconds, nanoseconds); // You can also create an EventTime object like this // EventTime eventTime = EventTime.fromEpochMilli(System.currentTimeMillis()); diff --git a/src/main/java/org/komamitsu/fluency/EventTime.java b/src/main/java/org/komamitsu/fluency/EventTime.java index bfe87007..24338126 100644 --- a/src/main/java/org/komamitsu/fluency/EventTime.java +++ b/src/main/java/org/komamitsu/fluency/EventTime.java @@ -25,43 +25,82 @@ import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.ByteOrder; @JsonSerialize(using = EventTime.Serializer.class) public class EventTime { - private final int seconds; - private final int nanoSeconds; - - public static EventTime fromEpoch(int epochSeconds) + private final long seconds; + private final long nanoseconds; + + /** + * Constructs an EventTime. + * + * @param epochSeconds the epoch seconds. This should be a 32-bit value. + */ + public static EventTime fromEpoch(long epochSeconds) { return new EventTime(epochSeconds, 0); } - public static EventTime fromEpoch(int epochSeconds, int nanoSeconds) + /** + * Constructs an EventTime. + * + * @param epochSeconds the epoch seconds. This should be a 32-bit value. + * @param nanoseconds the nanoseconds. This should be a 32-bit value. + */ + public static EventTime fromEpoch(long epochSeconds, long nanoseconds) { - return new EventTime(epochSeconds, nanoSeconds); + return new EventTime(epochSeconds, nanoseconds); } - public static EventTime fromEpochMilli(long epochMilliSecond) + /** + * Constructs an EventTime. + * + * @param epochMillisecond the epoch milli seconds. + * This should be a 32-bit value. + */ + public static EventTime fromEpochMilli(long epochMillisecond) { - return new EventTime((int) (epochMilliSecond/ 1000), (int) ((epochMilliSecond % 1000) * 1000000)); + return new EventTime(epochMillisecond/ 1000, (epochMillisecond % 1000) * 1000000); } - public EventTime(int seconds, int nanoSeconds) + /** + * Constructs an EventTime. + * + * @param seconds the epoch seconds. This should be a 32-bit value. + * @param nanoseconds the nanoseconds. This should be a 32-bit value. + */ + public EventTime(long seconds, long nanoseconds) { + if (seconds >> 32 != 0) { + throw new IllegalArgumentException("`seconds` should be a 32-bit value"); + } + + if (nanoseconds >> 32 != 0) { + throw new IllegalArgumentException("`nanoseconds` should be a 32-bit value"); + } + this.seconds = seconds; - this.nanoSeconds = nanoSeconds; + this.nanoseconds = nanoseconds; } - public int getSeconds() + public long getSeconds() { return seconds; } - public int getNanoSeconds() + public long getNanoseconds() + { + return nanoseconds; + } + + /** + * @deprecated As of release 1.9, replaced by {@link #getNanoseconds()} + */ + @Deprecated + public long getNanoSeconds() { - return nanoSeconds; + return nanoseconds; } @Override @@ -79,14 +118,14 @@ public boolean equals(Object o) if (seconds != eventTime.seconds) { return false; } - return nanoSeconds == eventTime.nanoSeconds; + return nanoseconds == eventTime.nanoseconds; } @Override public int hashCode() { - int result = seconds; - result = 31 * result + nanoSeconds; + int result = (int) (seconds ^ (seconds >>> 32)); + result = 31 * result + (int) (nanoseconds ^ (nanoseconds >>> 32)); return result; } @@ -95,7 +134,7 @@ public String toString() { return "EventTime{" + "seconds=" + seconds + - ", nanoSeconds=" + nanoSeconds + + ", nanoseconds=" + nanoseconds + '}'; } @@ -133,7 +172,7 @@ public void serialize(EventTime value, JsonGenerator gen, SerializerProvider pro // |fixext8|type| 32bits integer BE | 32bits integer BE | // +-------+----+----+----+----+----+----+----+----+----+ ByteBuffer buffer = ByteBuffer.allocate(8); - buffer.putInt(value.seconds).putInt(value.nanoSeconds); + buffer.putInt((int) value.seconds).putInt((int) value.nanoseconds); messagePackGenerator.writeExtensionType(new MessagePackExtensionType((byte)0x0, buffer.array())); } } diff --git a/src/test/java/org/komamitsu/fluency/EventTimeTest.java b/src/test/java/org/komamitsu/fluency/EventTimeTest.java index 3290bc3a..4c9e2b36 100644 --- a/src/test/java/org/komamitsu/fluency/EventTimeTest.java +++ b/src/test/java/org/komamitsu/fluency/EventTimeTest.java @@ -23,8 +23,6 @@ import org.msgpack.jackson.dataformat.MessagePackFactory; import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Date; import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; @@ -36,38 +34,77 @@ public void instantiation() { { long now = System.currentTimeMillis(); - EventTime eventTime = EventTime.fromEpoch((int) (now / 1000)); - assertThat(eventTime.getSeconds(), is((int) (now / 1000))); - assertThat(eventTime.getNanoSeconds(), is(0)); + EventTime eventTime = EventTime.fromEpoch(now / 1000); + assertThat(eventTime.getSeconds(), is(now / 1000)); + assertThat(eventTime.getNanoseconds(), is(0L)); } { long now = System.currentTimeMillis(); - EventTime eventTime = EventTime.fromEpoch((int) (now / 1000), 999999999); - assertThat(eventTime.getSeconds(), is((int) (now / 1000))); - assertThat(eventTime.getNanoSeconds(), is(999999999)); + EventTime eventTime = EventTime.fromEpoch(now / 1000, 999999999L); + assertThat(eventTime.getSeconds(), is(now / 1000)); + assertThat(eventTime.getNanoseconds(), is(999999999L)); } { long now = System.currentTimeMillis(); EventTime eventTime = EventTime.fromEpochMilli(now); - assertThat(eventTime.getSeconds(), is((int) (now / 1000))); - assertThat(eventTime.getNanoSeconds(), Matchers.is((int) (now % 1000 * 1000000))); + assertThat(eventTime.getSeconds(), is(now / 1000)); + assertThat(eventTime.getNanoseconds(), Matchers.is(now % 1000 * 1000000)); } + + { + EventTime eventTime = EventTime.fromEpoch(0xFFFFFFFFL, 0xFFFFFFFFL); + assertThat(eventTime.getSeconds(), is(0xFFFFFFFFL)); + assertThat(eventTime.getNanoseconds(), is(0xFFFFFFFFL)); + } + } + + @Test(expected = IllegalArgumentException.class) + public void instantiationWithTooLargeSeconds() + { + EventTime.fromEpoch(0x100000000L, 0L); + } + + @Test(expected = IllegalArgumentException.class) + public void instantiationWithTooLargeNanoSeconds() + { + EventTime.fromEpoch(0L, 0x100000000L); } @Test public void serialize() throws JsonProcessingException { - long now = System.currentTimeMillis(); - EventTime eventTime = EventTime.fromEpoch((int) (now / 1000), 999999999); - ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); - byte[] bytes = objectMapper.writeValueAsBytes(eventTime); - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - assertThat(byteBuffer.get(), is((byte) 0xD7)); - assertThat(byteBuffer.get(), is((byte) 0x00)); - assertThat(byteBuffer.getInt(), is((int) (now / 1000))); - assertThat(byteBuffer.getInt(), is(999999999)); + { + long now = System.currentTimeMillis(); + EventTime eventTime = EventTime.fromEpoch(now / 1000, 999999999); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + byte[] bytes = objectMapper.writeValueAsBytes(eventTime); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + assertThat(byteBuffer.get(), is((byte) 0xD7)); + assertThat(byteBuffer.get(), is((byte) 0x00)); + assertThat(byteBuffer.getInt(), is((int) (now / 1000))); + assertThat(byteBuffer.getInt(), is(999999999)); + } + + { + EventTime eventTime = EventTime.fromEpoch(0xFFEEDDCCL, 0xFEDCBA98L); + ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + byte[] bytes = objectMapper.writeValueAsBytes(eventTime); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + assertThat(byteBuffer.get(), is((byte) 0xD7)); + assertThat(byteBuffer.get(), is((byte) 0x00)); + + assertThat(byteBuffer.get(), is((byte) 0xFF)); + assertThat(byteBuffer.get(), is((byte) 0xEE)); + assertThat(byteBuffer.get(), is((byte) 0xDD)); + assertThat(byteBuffer.get(), is((byte) 0xCC)); + + assertThat(byteBuffer.get(), is((byte) 0xFE)); + assertThat(byteBuffer.get(), is((byte) 0xDC)); + assertThat(byteBuffer.get(), is((byte) 0xBA)); + assertThat(byteBuffer.get(), is((byte) 0x98)); + } } -} \ No newline at end of file +}