package com.fasterxml.jackson.dataformat.ion.jsr310;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.ZoneOffset;
import com.amazon.ion.Timestamp;
final class TimestampUtils {
private static final BigDecimal ONE_THOUSAND = new BigDecimal("1000");
private static final BigDecimal ONE_MILLION = new BigDecimal("1000000");
private static final BigDecimal ONE_BILLION = new BigDecimal("1000000000");
private TimestampUtils() {}
static Timestamp toTimestamp(Instant instant, ZoneOffset offset) {
final Integer offsetMinutes = offset == null ? null
: secondsToMinutes(offset.getTotalSeconds());
return Timestamp.forMillis(getFractionalMillis(instant), offsetMinutes);
}
static Instant toInstant(Timestamp timestamp) {
final BigDecimal decSeconds = timestamp.getDecimalMillis().divide(ONE_THOUSAND);
final long epocSeconds = decSeconds.longValue();
final long nanoAdjustment = decSeconds.subtract(BigDecimal.valueOf(epocSeconds))
.multiply(ONE_BILLION)
.longValue();
return Instant.ofEpochSecond(epocSeconds, nanoAdjustment);
}
static BigDecimal getFractionalSeconds(Instant instant) {
final BigDecimal epochSeconds = BigDecimal.valueOf(instant.getEpochSecond());
final BigDecimal nanos = BigDecimal.valueOf(instant.getNano());
return epochSeconds.add(nanos.divide(ONE_BILLION));
}
static BigDecimal getFractionalMillis(Instant instant) {
final BigDecimal epochSeconds = BigDecimal.valueOf(instant.getEpochSecond());
final BigDecimal nanos = BigDecimal.valueOf(instant.getNano());
return epochSeconds.multiply(ONE_THOUSAND)
.add(nanos.divide(ONE_MILLION));
}
static Instant fromFractionalSeconds(BigDecimal seconds) {
long secondsOnly;
int nanosOnly;
BigDecimal nanoseconds = seconds.scaleByPowerOfTen(9);
if (nanoseconds.precision() - nanoseconds.scale() <= 0) {
secondsOnly = nanosOnly = 0;
}
else if (seconds.scale() < -63) {
secondsOnly = nanosOnly = 0;
}
else {
secondsOnly = seconds.longValue();
nanosOnly = nanoseconds.subtract(new BigDecimal(secondsOnly).scaleByPowerOfTen(9)).intValue();
if (secondsOnly < 0 && secondsOnly > Instant.MIN.getEpochSecond()) {
nanosOnly = Math.abs(nanosOnly);
}
}
return Instant.ofEpochSecond(secondsOnly, nanosOnly) ;
}
private static int secondsToMinutes(int seconds) {
return Math.floorDiv(seconds, 60);
}
}