Skip to content

Commit

Permalink
Removed redundant tests now that we have reverse option running the t…
Browse files Browse the repository at this point in the history
…ests bi-directionally.

Added code to detect redundant tests - this was used to determine which tests were redundant.
Removed IEEE 754 issues with the date-time calculations by carefully and judiciously using BigDecimal internally.
  • Loading branch information
jdereg committed Mar 3, 2024
1 parent bb4e780 commit 22dc4c4
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 510 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@
* limitations under the License.
*/
final class BigDecimalConversions {
static final BigDecimal BILLION = BigDecimal.valueOf(1_000_000_000);
static final BigDecimal GRAND = BigDecimal.valueOf(1000);

private BigDecimalConversions() { }

static Calendar toCalendar(Object from, Converter converter) {
BigDecimal seconds = (BigDecimal) from;
BigDecimal millis = seconds.multiply(BigDecimal.valueOf(1000));
BigDecimal millis = seconds.multiply(GRAND);
Calendar calendar = GregorianCalendar.getInstance(converter.getOptions().getTimeZone());
calendar.setTimeInMillis(millis.longValue());
return calendar;
Expand All @@ -59,7 +60,7 @@ static Duration toDuration(Object from, Converter converter) {

static LocalTime toLocalTime(Object from, Converter converter) {
BigDecimal seconds = (BigDecimal) from;
BigDecimal nanos = seconds.multiply(BigDecimal.valueOf(1_000_000_000));
BigDecimal nanos = seconds.multiply(BILLION);
try {
return LocalTime.ofNanoOfDay(nanos.longValue());
}
Expand Down Expand Up @@ -108,4 +109,8 @@ static UUID toUUID(Object from, Converter converter) {
BigInteger bigInt = ((BigDecimal) from).toBigInteger();
return BigIntegerConversions.toUUID(bigInt, converter);
}

static BigDecimal secondsAndNanosToDouble(long seconds, long nanos) {
return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9));
}
}
27 changes: 27 additions & 0 deletions src/main/java/com/cedarsoftware/util/convert/ByteConversions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.cedarsoftware.util.convert;

/**
* @author John DeRegnaucourt ([email protected])
* <br>
* Copyright (c) Cedar Software LLC
* <br><br>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <br><br>
* <a href="http://www.apache.org/licenses/LICENSE-2.0">License</a>
* <br><br>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class ByteConversions {
private ByteConversions() {}

static Character toCharacter(Object from, Converter converter) {
Byte b = (Byte) from;
return (char) b.byteValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static boolean toBoolean(Object from, Converter converter) {
return (c == 1) || (c == 't') || (c == 'T') || (c == '1') || (c == 'y') || (c == 'Y');
}

// downcasting -- not always a safe conversino
// down casting -- not always a safe conversion
static byte toByte(Object from, Converter converter) {
return (byte) (char) from;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ private static void buildFactoryConversions() {
// Character/char conversions supported
CONVERSION_DB.put(pair(Void.class, char.class), VoidConversions::toCharacter);
CONVERSION_DB.put(pair(Void.class, Character.class), VoidConversions::toNull);
CONVERSION_DB.put(pair(Byte.class, Character.class), NumberConversions::toCharacter);
CONVERSION_DB.put(pair(Byte.class, Character.class), ByteConversions::toCharacter);
CONVERSION_DB.put(pair(Short.class, Character.class), NumberConversions::toCharacter);
CONVERSION_DB.put(pair(Integer.class, Character.class), NumberConversions::toCharacter);
CONVERSION_DB.put(pair(Long.class, Character.class), NumberConversions::toCharacter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ private DoubleConversions() { }
static Instant toInstant(Object from, Converter converter) {
double d = (Double) from;
long seconds = (long) d;
long nanoAdjustment = (long) ((d - seconds) * 1_000_000_000L);
return Instant.ofEpochSecond(seconds, nanoAdjustment);
// Calculate nanoseconds by taking the fractional part of the double and multiplying by 1_000_000_000,
// rounding to the nearest long to maintain precision.
long nanos = Math.round((d - seconds) * 1_000_000_000);
return Instant.ofEpochSecond(seconds, nanos);
}

static Date toDate(Object from, Converter converter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,12 @@ static BigInteger toBigInteger(Object from, Converter converter) {

static double toDouble(Object from, Converter converter) {
Duration duration = (Duration) from;
return duration.getSeconds() + duration.getNano() / 1_000_000_000d;
return BigDecimalConversions.secondsAndNanosToDouble(duration.getSeconds(), duration.getNano()).doubleValue();
}

static BigDecimal toBigDecimal(Object from, Converter converter) {
Duration duration = (Duration) from;
BigDecimal seconds = new BigDecimal(duration.getSeconds());

// Convert nanoseconds to fractional seconds and add to seconds
BigDecimal fracSec = BigDecimal.valueOf(duration.getNano(), 9);
return seconds.add(fracSec);
return BigDecimalConversions.secondsAndNanosToDouble(duration.getSeconds(), duration.getNano());
}

static Timestamp toTimestamp(Object from, Converter converter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ static long toLong(Object from, Converter converter) {
*/
static double toDouble(Object from, Converter converter) {
Instant instant = (Instant) from;
long seconds = instant.getEpochSecond();
int nanoAdjustment = instant.getNano();
return (double) seconds + (double) nanoAdjustment / 1_000_000_000d;
return BigDecimalConversions.secondsAndNanosToDouble(instant.getEpochSecond(), instant.getNano()).doubleValue();
}

static AtomicLong toAtomicLong(Object from, Converter converter) {
Expand Down Expand Up @@ -96,9 +94,7 @@ static BigInteger toBigInteger(Object from, Converter converter) {

static BigDecimal toBigDecimal(Object from, Converter converter) {
Instant instant = (Instant) from;
long seconds = instant.getEpochSecond();
int nanos = instant.getNano();
return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9));
return BigDecimalConversions.secondsAndNanosToDouble(instant.getEpochSecond(), instant.getNano());
}

static LocalDateTime toLocalDateTime(Object from, Converter converter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ static Map<String, Object> toMap(Object from, Converter converter) {
static double toDouble(Object from, Converter converter) {
OffsetDateTime odt = (OffsetDateTime) from;
Instant instant = odt.toInstant();

long epochSecond = instant.getEpochSecond();
int nano = instant.getNano();

// Convert seconds to milliseconds and add the fractional milliseconds
return epochSecond + nano / 1_000_000_000.0d;
return BigDecimalConversions.secondsAndNanosToDouble(instant.getEpochSecond(), instant.getNano()).doubleValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private TimestampConversions() {}

static double toDouble(Object from, Converter converter) {
Duration d = toDuration(from, converter);
return d.getSeconds() + d.getNano() / 1_000_000_000d;
return BigDecimalConversions.secondsAndNanosToDouble(d.getSeconds(), d.getNano()).doubleValue();
}

static BigDecimal toBigDecimal(Object from, Converter converter) {
Expand All @@ -47,9 +47,8 @@ static BigInteger toBigInteger(Object from, Converter 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);
return Duration.between(Instant.EPOCH, timestampInstant);
}

static OffsetDateTime toOffsetDateTime(Object from, Converter converter) {
Expand Down
Loading

0 comments on commit 22dc4c4

Please sign in to comment.