PR #177 introduced a subtle bug in the binary reader.
Each Timestamp has a decimal field representing its number of fractional seconds. After reading the decimal's exponent field from the input stream, the reader then casts it to an unsigned int.
In most cases this behavior is fine. A decimal's scale field is the negation of the exponent. We don't expect a negative scale; that would indicate a fractional seconds value greater than 1 and therefore represent some number of whole seconds.
However, there's an exception to this: a fractional seconds of 0d1 or any other zero-coefficient, positive-exponent decimal value. In this case, scale is -1 and casting it to a uint8 turns it into the value 255.
Downstream, the constructor NewTimestampWithFractionalSeconds detects that 255 is greater than the maximum supported fractional seconds precision and trims it to 9:
PR #177 introduced a subtle bug in the binary reader.
Each
Timestamp
has adecimal
field representing its number of fractional seconds. After reading the decimal'sexponent
field from the input stream, the reader then casts it to an unsigned int.In most cases this behavior is fine. A
decimal
'sscale
field is the negation of the exponent. We don't expect a negativescale
; that would indicate a fractional seconds value greater than1
and therefore represent some number of whole seconds.However, there's an exception to this: a fractional seconds of
0d1
or any other zero-coefficient, positive-exponentdecimal
value. In this case,scale
is-1
and casting it to auint8
turns it into the value255
.Downstream, the constructor
NewTimestampWithFractionalSeconds
detects that255
is greater than the maximum supported fractional seconds precision and trims it to9
:https://github.com/amzn/ion-go/blob/7d02b52c1f33e23baf05d066dcbef6556343989a/ion/timestamp.go#L157-L161
The end result is a
Timestamp
value with a (correct) coefficient of zero but an erroneously set precision of9
.cc @byronlin13 @justing-bq