[#8083] Add Interval.toDuration()

This commit is contained in:
lukaseder 2018-12-03 14:30:33 +01:00
parent a6a23970ce
commit 6d415a8d76
4 changed files with 85 additions and 1 deletions

View File

@ -39,6 +39,7 @@ package org.jooq.types;
import java.time.Duration;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -219,13 +220,54 @@ public final class DayToSecond extends Number implements Interval, Comparable<Da
return result;
}
/**
* Load a {@link Double} representation of a
* <code>INTERVAL DAY TO SECOND</code> by assuming standard 24 hour days and
* 60 second minutes.
*
* @param second The number of seconds
* @param nanos The number of nano seconds
* @return The loaded <code>INTERVAL DAY TO SECOND</code> object
*/
public static DayToSecond valueOf(long second, int nanos) {
long abs = Math.abs(second);
int s = (int) (abs % 60L); abs = abs / 60L;
int m = (int) (abs % 60L); abs = abs / 60L;
int h = (int) (abs % 24L); abs = abs / 24L;
int d = (int) abs;
DayToSecond result = new DayToSecond(d, h, m, s, nanos);
if (second < 0)
result = result.neg();
return result;
}
/**
* Transform a {@link Duration} into a {@link DayToSecond} interval by
* taking its number of milliseconds.
*/
public static DayToSecond valueOf(Duration duration) {
return duration == null ? null : valueOf(duration.toMillis());
if (duration == null)
return null;
long s = duration.get(ChronoUnit.SECONDS);
int n = (int) duration.get(ChronoUnit.NANOS);
if (s < 0) {
n = 1_000_000_000 - n;
s++;
}
return valueOf(s, n);
}
@Override
public final Duration toDuration() {
return Duration.ofSeconds((long) getTotalSeconds(), getSign() * getNano());
}

View File

@ -38,6 +38,8 @@
package org.jooq.types;
import java.io.Serializable;
import java.time.Duration;
import java.time.YearMonth;
import org.jooq.Field;
import org.jooq.SQLDialect;
@ -174,4 +176,23 @@ public interface Interval extends Serializable {
* @see Number#shortValue()
*/
short shortValue();
/**
* Get a duration representation of this interval.
* <p>
* There is an obvious {@link Duration} representation for
* {@link DayToSecond} intervals. If the interval contains {@link YearMonth}
* information, then the corresponding duration will use:
* <p>
* <ul>
* <li>1 year = 365.25 days</li>
* <li>1 month = 30 days</li>
* </ul>
* <p>
* This corresponds to PostgreSQL's
* <code>EXTRACT(EPOCH FROM my_interval)</code> behaviour.
*/
Duration toDuration();
}

View File

@ -37,6 +37,7 @@
*/
package org.jooq.types;
import java.time.Duration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -146,6 +147,19 @@ public final class YearToMonth extends Number implements Interval, Comparable<Ye
return null;
}
@Override
public final Duration toDuration() {
long hours = years * 8766L // 365.25 * 24
+ months * 720L; // 30 * 24
if (negative)
hours = -hours;
return Duration.ofHours(hours);
}
// -------------------------------------------------------------------------
// XXX Interval API
// -------------------------------------------------------------------------

View File

@ -125,6 +125,13 @@ public final class YearToSecond extends Number implements Interval, Comparable<Y
return duration == null ? null : valueOf(duration.toMillis());
}
@Override
public final Duration toDuration() {
return yearToMonth.toDuration().plus(dayToSecond.toDuration());
}
/**
* Transform a {@link Period} into a {@link YearToSecond} interval.
*/