Adds support for writing binary Ion 1.1 timestamps#618
Adds support for writing binary Ion 1.1 timestamps#618popematt merged 4 commits intoamazon-ion:ion-11-encodingfrom
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report? Let us know! |
| import com.amazon.ion.Decimal; | ||
| import com.amazon.ion.IonType; | ||
| import com.amazon.ion.Timestamp; | ||
| import com.amazon.ion.impl.bin.utf8.Utf8StringEncoder; |
There was a problem hiding this comment.
These were unused imports.
| "false, 5F", | ||
| }) | ||
| public void testWriteBooleanValue(Boolean value, String expectedBytes) { | ||
| public void testWriteBooleanValue(boolean value, String expectedBytes) { |
There was a problem hiding this comment.
This is an incidental change. Then writeBooleanValue method accepts boolean, so I made the test do the same.
| public void testWriteIntegerValueForBigInteger(BigInteger value, String expectedBytes) { | ||
| assertWritingValue(expectedBytes, value, IonEncoder_1_1::writeIntValue); |
There was a problem hiding this comment.
This is also an incidental change since I realized that JUnit already knows how to convert to BigInteger.
| public int writeFixedUInt(final long value) { | ||
| if (value < 0) { | ||
| throw new IllegalArgumentException("Attempted to write a FlexUInt for " + value); | ||
| throw new IllegalArgumentException("Attempted to write a FixedUInt for " + value); |
There was a problem hiding this comment.
Just fixing a typo that I noticed while working on Timestamps.
tgregg
left a comment
There was a problem hiding this comment.
I still need to double-check the tests for you, but leaving these comments here for now.
| } | ||
|
|
||
| // Condition 2: The fractional seconds are a common precision. | ||
| int secondsScale = value.getDecimalSecond().scale(); |
There was a problem hiding this comment.
getDecimalSecond() creates a new BigDecimal on each call. Let's use getZFractionalSecond() instead. It's deprecated, but if we ever get around to removing it we'll replace it with some internal accessor. Note: this also requires a null check.
|
|
||
| // Condition 2: The fractional seconds are a common precision. | ||
| int secondsScale = value.getDecimalSecond().scale(); | ||
| if (secondsScale != 0 && secondsScale != 3 && secondsScale != 6 && secondsScale != 9) { |
There was a problem hiding this comment.
Note: in my initial prototype I used secondsScale % 3 != 0 || secondsScale > 9. Comparing these alternatives, I think it's pretty much a wash. In the common case (that the scale matches one of the common precisions) my suggestion always requires two comparisons, but it also has the modulo. Yours varies depending on the actual precision. One comparison if the scale is 0, two if it's 3, and so on. Leaving this comment in case you feel like forming a strong opinion on which one is preferable.
There was a problem hiding this comment.
I don't have a preference, and I suspect that it will not have very significant difference. I'll create an issue to revisit this later.
| static final int L_TIMESTAMP_OFFSET_BIT_OFFSET = 34; | ||
| static final int L_TIMESTAMP_SECOND_BIT_OFFSET = 44; |
There was a problem hiding this comment.
This looks off. The offset is 12 bits, but here the second bit is only 10 after the offset bits.
|
|
||
| bits |= ((long) value.getSecond()) << S_U_TIMESTAMP_SECOND_BIT_OFFSET; | ||
|
|
||
| int secondsScale = value.getDecimalSecond().scale(); |
There was a problem hiding this comment.
getZFractionalSecond() here too, and below
|
|
||
| int secondsScale = value.getDecimalSecond().scale(); | ||
| if (secondsScale != 0) { | ||
| long fractionalSeconds = value.getDecimalSecond().remainder(BigDecimal.ONE).movePointRight(secondsScale).longValue(); |
There was a problem hiding this comment.
I see value.unscaledValue().longValue() in my prototype. Maybe you can get that to work. Remember that any BigDecimal method that returns BigDecimal allocates a new one, so we want to minimize that.
| @ParameterizedTest | ||
| @CsvSource({ | ||
| // OpCode MYYYYYYY DDDDDMMM mmmHHHHH ooooommm ssssssoo ffffffff ffffffff ffffffff ..ffffff | ||
| "2023-10-15T01:00-14:00, 01111000 00110101 01111101 00000001 01000000 00000010", |
There was a problem hiding this comment.
Should the offset bits all be zero for this one?
There was a problem hiding this comment.
Why yes, it should. 😅
I've gone and manually double checked several more test cases with offsets both in the short form and the long form timestamps. I forgot about adjusting the offset for the short form, but the long form looks okay.
Issue #, if available:
None
Description of changes:
Adds support for writing binary Ion 1.1 timestamps.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.