d2a4u/meteor

The default Encoder[Instant] instance fails for dates very far in the future

Closed this issue · 1 comments

Description
The default Encoder[Instant] instance fails with a java.lang.ArithmeticException: long overflow error when trying to encode dates that are very far in the future.

The cause of the bug is that the default Encoder represents time values as Long millisecond timestamps, although Instant is capable of storing much larger values than what a Long can.

Example

import meteor.syntax._
import java.time.Instant

val t = Instant.ofEpochMilli(Long.MaxValue).plusMillis(1)
t.asAttributeValue // throws ArithmeticException

Possible solution
Changing Encoder[Instant] to represent values as ISO strings.
This would also have the added benefit of not truncating sub-millisecond values.

implicit val InstantCodec: Codec[Instant] =
  new Codec[Instant] {
    def read(av: AttributeValue): Either[DecoderError, Instant] =
      av.as[String].flatMap { str =>
        Either
          .catchNonFatal(Instant.parse(str))
          .left
          .map(err => DecoderError(err.getMessage(), err.getCause().some))
      }

    def write(a: Instant): AttributeValue = a.toString().asAttributeValue

  }
d2a4u commented

good point. However, this only happens for very very large value. By changing the default Codec, it potentially will break all existing data which has been written as Long. Personally I think if you are effected by this bug, you can provide your custom Codec instead of using the one provided by the lib. A proper fix would be provide a Codec that is compatible with both formats.