Consolidate conversion from Duration to Period in DurationConverter (#786)

* Consolidate conversion from Duration to Period in DurationConverter

* Resolve comment
This commit is contained in:
Shicong Huang 2020-09-01 11:29:28 -04:00 committed by GitHub
parent 5a08ce498e
commit 393c388e0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 14 deletions

View file

@ -40,11 +40,17 @@ public class DurationConverter implements AttributeConverter<Duration, PGInterva
if (duration == null) {
return new PGInterval();
}
// When the period is created from duration by calling duration.toPeriod(), only precise fields
// in the period type will be used. Thus, only the hour, minute, second and millisecond fields
// on the period will be used. The year, month, week and day fields will not be populated:
// 1. If the duration is small, less than one day, then this method will just set
// hours/minutes/seconds correctly.
// 2. If the duration is larger than one day then all the remaining duration will
// be stored in the largest available field, hours in this case.
// So, when we convert the period to a PGInterval instance, we set the days field by extracting
// it from period's hours field.
Period period = duration.toPeriod();
PGInterval interval = new PGInterval();
Period period = new Period(duration);
// For some reason when the period is created from the duration, it does not set days, but
// instead just a total number of hours. Years and months are not created because those can
// differ in length of milliseconds.
interval.setDays(period.getHours() / 24);
interval.setHours(period.getHours() % 24);
interval.setMinutes(period.getMinutes());

View file

@ -51,22 +51,37 @@ public class DurationConverterTest {
.plus(Duration.standardMinutes(30))
.plus(Duration.standardSeconds(15))
.plus(Duration.millis(7));
DurationTestEntity entity = new DurationTestEntity(testDuration);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
DurationTestEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(DurationTestEntity.class, "id"));
assertThat(persisted.duration.getMillis()).isEqualTo(testDuration.getMillis());
assertPersistedEntityHasSameDuration(testDuration);
}
@Test
void testRoundTripLargeNumberOfDays() {
Duration testDuration =
Duration.standardDays(10001).plus(Duration.standardHours(100)).plus(Duration.millis(790));
DurationTestEntity entity = new DurationTestEntity(testDuration);
jpaTm().transact(() -> jpaTm().getEntityManager().persist(entity));
assertPersistedEntityHasSameDuration(testDuration);
}
@Test
void testRoundTripLessThanOneDay() {
Duration testDuration =
Duration.standardHours(15)
.plus(Duration.standardMinutes(40))
.plus(Duration.standardSeconds(50));
assertPersistedEntityHasSameDuration(testDuration);
}
@Test
void testRoundTripExactOneDay() {
Duration testDuration = Duration.standardDays(1);
assertPersistedEntityHasSameDuration(testDuration);
}
private void assertPersistedEntityHasSameDuration(Duration duration) {
DurationTestEntity entity = new DurationTestEntity(duration);
jpaTm().transact(() -> jpaTm().saveNew(entity));
DurationTestEntity persisted =
jpaTm().transact(() -> jpaTm().getEntityManager().find(DurationTestEntity.class, "id"));
assertThat(persisted.duration.getMillis()).isEqualTo(testDuration.getMillis());
assertThat(persisted.duration.getMillis()).isEqualTo(duration.getMillis());
}
@Entity(name = "TestEntity") // Override entity name to avoid the nested class reference.