TimestampIgnoreMillisValueComparerBase.java
package org.dbunit.assertion.comparer.value;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.dbunit.DatabaseUnitException;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.datatype.DataType;
import org.dbunit.dataset.datatype.TypeCastException;
/**
* Base class for {@link ValueComparer} implementations that verify Timestamps,
* ignoring the milliseconds.
*
* @author Jeff Jensen
* @since 3.1.0
*/
public abstract class TimestampIgnoreMillisValueComparerBase
extends ValueComparerTemplateBase
{
private static final int ONE_SECOND_IN_MILLIS = 1000;
@Override
protected boolean isExpected(final ITable expectedTable,
final ITable actualTable, final int rowNum, final String columnName,
final DataType dataType, final Object expectedValue,
final Object actualValue) throws DatabaseUnitException
{
final boolean isExpected;
if (expectedValue == null || actualValue == null)
{
isExpected = isExpectedWithNull(expectedValue, actualValue);
} else
{
isExpected =
isExpectedWithoutNull(dataType, expectedValue, actualValue);
}
return isExpected;
}
/**
* Determines whether the actual value matches the expected value when at least one of them
* is <code>null</code>.
*
* @param expectedValue the expected value, possibly <code>null</code>.
* @param actualValue the actual value, possibly <code>null</code>.
* @return <code>true</code> if the values are considered equal.
*/
protected boolean isExpectedWithNull(final Object expectedValue,
final Object actualValue)
{
final boolean isExpected;
if (expectedValue == null)
{
isExpected = actualValue == null;
} else
{
isExpected = expectedValue.equals(actualValue);
}
return isExpected;
}
/**
* Determines whether the actual value matches the expected value, ignoring milliseconds,
* given that neither is <code>null</code>.
*
* @param dataType the column's data type.
* @param expectedValue the expected value, never <code>null</code>.
* @param actualValue the actual value, never <code>null</code>.
* @return <code>true</code> if the values are considered equal, ignoring milliseconds.
* @throws TypeCastException if a value cannot be converted for comparison.
*/
protected boolean isExpectedWithoutNull(final DataType dataType,
final Object expectedValue, final Object actualValue)
throws TypeCastException
{
assertNotNull(expectedValue, "expectedValue is null.");
assertNotNull(actualValue, "actualValue is null.");
long actualTime = convertValueToTimeInMillis(actualValue);
long expectedTime = convertValueToTimeInMillis(expectedValue);
actualTime = truncateToSecond(actualTime);
expectedTime = truncateToSecond(expectedTime);
return compareTimestamps(dataType, actualTime, expectedTime);
}
private long truncateToSecond(final long timeInMilliseconds)
{
return ONE_SECOND_IN_MILLIS
* (timeInMilliseconds / ONE_SECOND_IN_MILLIS);
}
/**
* Converts the given value to milliseconds since the epoch.
*
* @param timestampValue the value to convert, a {@link Timestamp} or a {@link String}
* formatted as <code>yyyy-MM-dd HH:mm:ss</code>.
* @return the value converted to milliseconds since the epoch, or 0 if the value is neither.
*/
protected long convertValueToTimeInMillis(final Object timestampValue)
{
final Timestamp timestamp;
if (timestampValue instanceof Timestamp)
{
timestamp = (Timestamp) timestampValue;
} else if (timestampValue instanceof String)
{
final DateTimeFormatter dateFormat =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
final LocalDateTime parsedDate =
LocalDateTime.parse((String) timestampValue, dateFormat);
timestamp = Timestamp.valueOf(parsedDate);
} else
{
timestamp = null;
}
final long time;
if (timestamp == null)
{
time = 0L;
} else
{
time = timestamp.getTime();
}
return time;
}
abstract boolean compareTimestamps(final DataType dataType,
final long actualTime, final long expectedTime)
throws TypeCastException;
}