Skip to content

Commit

Permalink
For BigInteger and BigDecimal conversions, ensuring that temporal cla…
Browse files Browse the repository at this point in the history
…sses that handle nanos, the nanos are retained. For BigDecimal, the decimal portion of the number is decimal milliseconds - the whole portion of the BigDecimal is milliseconds "dot" fractional milliseconds (up to 6 decimal places = 1 billionth of a second, or a millionth of a microsecond). For BigInteger, the conversion is always in BigInteger nanoseconds, period. BigInteger has many of these conversions completed, but not all. After that, BigDecimal is next. There are a few more to add for Long, but when using Long it is always working with milliseconds only.
  • Loading branch information
jdereg committed Feb 19, 2024
1 parent d8ce0ac commit 32adb24
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
* limitations under the License.
*/
final class BigDecimalConversions {
private BigDecimalConversions() { }

static Instant toInstant(Object from, Converter converter) {
BigDecimal time = (BigDecimal) from;
long seconds = time.longValue() / 1000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.util.UUID;

/**
Expand All @@ -22,6 +25,11 @@
* limitations under the License.
*/
final class BigIntegerConversions {
static final BigInteger MILLION = BigInteger.valueOf(1_000_000);
static final BigInteger BILLION = BigInteger.valueOf(1_000_000_000);

private BigIntegerConversions() { }

static BigDecimal toBigDecimal(Object from, Converter converter) {
return new BigDecimal((BigInteger)from);
}
Expand Down Expand Up @@ -52,4 +60,41 @@ static UUID toUUID(Object from, Converter converter) {
// Create UUID from string
return UUID.fromString(uuidString);
}

/**
* Epoch nanos to Timestamp
*/
static Timestamp toTimestamp(Object from, Converter converter) {
BigInteger nanoseconds = (BigInteger) from;
Duration duration = toDuration(nanoseconds, converter);
Instant epoch = Instant.EPOCH;

// Add the duration to the epoch
Instant timestampInstant = epoch.plus(duration);

// Convert Instant to Timestamp
return Timestamp.from(timestampInstant);
}

/**
* Epoch nanos to Instant
*/
static Instant toInstant(Object from, Converter converter) {
BigInteger nanoseconds = (BigInteger) from;
BigInteger[] secondsAndNanos = nanoseconds.divideAndRemainder(BILLION);
long seconds = secondsAndNanos[0].longValue(); // Total seconds
int nanos = secondsAndNanos[1].intValue(); // Nanoseconds part
return Instant.ofEpochSecond(seconds, nanos);
}

/**
* Epoch nanos to Duration
*/
static Duration toDuration(Object from, Converter converter) {
BigInteger nanoseconds = (BigInteger) from;
BigInteger[] secondsAndNanos = nanoseconds.divideAndRemainder(BILLION);
long seconds = secondsAndNanos[0].longValue();
int nanos = secondsAndNanos[1].intValue();
return Duration.ofSeconds(seconds, nanos);
}
}
10 changes: 7 additions & 3 deletions src/main/java/com/cedarsoftware/util/convert/Converter.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,8 @@ private static void buildFactoryConversions() {
CONVERSION_DB.put(pair(AtomicLong.class, BigInteger.class), NumberConversions::integerTypeToBigInteger);
CONVERSION_DB.put(pair(Date.class, BigInteger.class), DateConversions::toBigInteger);
CONVERSION_DB.put(pair(java.sql.Date.class, BigInteger.class), DateConversions::toBigInteger);
CONVERSION_DB.put(pair(Timestamp.class, BigInteger.class), DateConversions::toBigInteger);
CONVERSION_DB.put(pair(Timestamp.class, BigInteger.class), TimestampConversions::toBigInteger);
CONVERSION_DB.put(pair(Duration.class, BigInteger.class), DurationConversions::toBigInteger);
CONVERSION_DB.put(pair(Instant.class, BigInteger.class), InstantConversions::toBigInteger);
CONVERSION_DB.put(pair(LocalDate.class, BigInteger.class), LocalDateConversions::toBigInteger);
CONVERSION_DB.put(pair(LocalDateTime.class, BigInteger.class), LocalDateTimeConversions::toBigInteger);
Expand Down Expand Up @@ -467,13 +468,14 @@ private static void buildFactoryConversions() {
CONVERSION_DB.put(pair(Integer.class, Timestamp.class), UNSUPPORTED);
CONVERSION_DB.put(pair(Long.class, Timestamp.class), NumberConversions::toTimestamp);
CONVERSION_DB.put(pair(Double.class, Timestamp.class), DoubleConversions::toTimestamp);
CONVERSION_DB.put(pair(BigInteger.class, Timestamp.class), NumberConversions::toTimestamp);
CONVERSION_DB.put(pair(BigInteger.class, Timestamp.class), BigIntegerConversions::toTimestamp);
CONVERSION_DB.put(pair(BigDecimal.class, Timestamp.class), BigDecimalConversions::toTimestamp);
CONVERSION_DB.put(pair(AtomicInteger.class, Timestamp.class), UNSUPPORTED);
CONVERSION_DB.put(pair(AtomicLong.class, Timestamp.class), NumberConversions::toTimestamp);
CONVERSION_DB.put(pair(Timestamp.class, Timestamp.class), DateConversions::toTimestamp);
CONVERSION_DB.put(pair(java.sql.Date.class, Timestamp.class), DateConversions::toTimestamp);
CONVERSION_DB.put(pair(Date.class, Timestamp.class), DateConversions::toTimestamp);
CONVERSION_DB.put(pair(Duration.class, Timestamp.class), DurationConversions::toTimestamp);
CONVERSION_DB.put(pair(Instant.class,Timestamp.class), InstantConversions::toTimestamp);
CONVERSION_DB.put(pair(LocalDate.class, Timestamp.class), LocalDateConversions::toTimestamp);
CONVERSION_DB.put(pair(LocalDateTime.class, Timestamp.class), LocalDateTimeConversions::toTimestamp);
Expand Down Expand Up @@ -718,6 +720,8 @@ private static void buildFactoryConversions() {
// Duration conversions supported
CONVERSION_DB.put(pair(Void.class, Duration.class), VoidConversions::toNull);
CONVERSION_DB.put(pair(Duration.class, Duration.class), Converter::identity);
CONVERSION_DB.put(pair(BigInteger.class, Duration.class), BigIntegerConversions::toDuration);
CONVERSION_DB.put(pair(Timestamp.class, Duration.class), TimestampConversions::toDuration);
CONVERSION_DB.put(pair(String.class, Duration.class), StringConversions::toDuration);
CONVERSION_DB.put(pair(Map.class, Duration.class), MapConversions::toDuration);

Expand All @@ -729,7 +733,7 @@ private static void buildFactoryConversions() {
CONVERSION_DB.put(pair(Integer.class, Instant.class), UNSUPPORTED);
CONVERSION_DB.put(pair(Long.class, Instant.class), NumberConversions::toInstant);
CONVERSION_DB.put(pair(Double.class, Instant.class), DoubleConversions::toInstant);
CONVERSION_DB.put(pair(BigInteger.class, Instant.class), NumberConversions::toInstant);
CONVERSION_DB.put(pair(BigInteger.class, Instant.class), BigIntegerConversions::toInstant);
CONVERSION_DB.put(pair(BigDecimal.class, Instant.class), BigDecimalConversions::toInstant);
CONVERSION_DB.put(pair(AtomicInteger.class, Instant.class), UNSUPPORTED);
CONVERSION_DB.put(pair(AtomicLong.class, Instant.class), NumberConversions::toInstant);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.cedarsoftware.util.convert;

import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.util.Map;

import com.cedarsoftware.util.CompactLinkedMap;
Expand Down Expand Up @@ -34,4 +37,20 @@ static Map toMap(Object from, Converter converter) {
target.put("nanos", nanos);
return target;
}

static BigInteger toBigInteger(Object from, Converter converter) {
Duration duration = (Duration) from;
BigInteger seconds = BigInteger.valueOf(duration.getSeconds());
BigInteger nanos = BigInteger.valueOf(duration.getNano());

// Convert seconds to nanoseconds and add the nanosecond part
return seconds.multiply(BigIntegerConversions.BILLION).add(nanos);
}

static Timestamp toTimestamp(Object from, Converter converter) {
Duration duration = (Duration) from;
Instant epoch = Instant.EPOCH;
Instant timeAfterDuration = epoch.plus(duration);
return Timestamp.from(timeAfterDuration);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,13 @@ static Calendar toCalendar(Object from, Converter converter) {
}

static BigInteger toBigInteger(Object from, Converter converter) {
return BigInteger.valueOf(toLong(from, converter));
Instant instant = (Instant) from;
// Get seconds and nanoseconds from the Instant
long seconds = instant.getEpochSecond();
int nanoseconds = instant.getNano();

// Convert the entire time to nanoseconds
return BigInteger.valueOf(seconds).multiply(BigIntegerConversions.BILLION).add(BigInteger.valueOf(nanoseconds));
}

static BigDecimal toBigDecimal(Object from, Converter converter) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.cedarsoftware.util.convert;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;

/**
* @author John DeRegnaucourt ([email protected])
Expand All @@ -21,6 +24,8 @@
* limitations under the License.
*/
final class TimestampConversions {
private static final BigInteger MILLION = BigInteger.valueOf(1_000_000);

private TimestampConversions() {}

static double toDouble(Object from, Converter converter) {
Expand All @@ -42,4 +47,16 @@ static BigDecimal toBigDecimal(Object from, Converter converter) {
// Convert time to fractional milliseconds
return BigDecimal.valueOf(epochMillis).add(BigDecimal.valueOf(nanoPart, 6)); // Dividing by 1_000_000 with scale 6
}

static BigInteger toBigInteger(Object from, Converter converter) {
Duration duration = toDuration(from, converter);
return DurationConversions.toBigInteger(duration, converter);
}

static Duration toDuration(Object from, Converter converter) {
Timestamp timestamp = (Timestamp) from;
Instant epoch = Instant.EPOCH;
Instant timestampInstant = timestamp.toInstant();
return Duration.between(epoch, timestampInstant);
}
}
Loading

0 comments on commit 32adb24

Please sign in to comment.