乔达持续时间转换为最近的ceil
Joda Duration convert to nearest ceil
我正在使用 Joda-Time Duration
来获取两个 DateTime
:
之间的持续时间
DateTime startTimeDate = new DateTime(startTimeDateInLong, DateTimeZone.UTC);
DateTime endTimeDate = new DateTime(endTimeDateInLong, DateTimeZone.UTC);
Duration duration = new Duration(startTimeDate, endTimeDate);
我想按照以下规则转换:
0-60 seconds --> 1 minute ..
1.5 - 1 hour --> 1 hour
1.6 hour - 2 hour --> 2 hour
我正在使用 duration.toStandardHours()
,但是 96 分钟它给了 1 小时,而不是我想要 2 小时。
Duration
class 没有按照您想要的方式对值进行四舍五入。即使您得到 1 小时 59 分 59 秒 999 毫秒的持续时间,toStandardHours()
也会 return 1
.
要得到你想要的结果,你必须得到以秒为单位的总数,然后相应地操作这个值。您可以使用 java.math.BigDecimal
class 和 java.math.RoundingMode
来控制值的舍入方式:
// 96-minutes duration
Duration duration = new Duration(96 * 60 * 1000);
long secs = duration.toStandardSeconds().getSeconds();
if (secs >= 3600) { // more than 1 hour
BigDecimal secondsPerHour = new BigDecimal(3600);
int hours = new BigDecimal(secs).divide(secondsPerHour, RoundingMode.HALF_DOWN).intValue();
System.out.println(hours + " hour" + (hours > 1 ? "s" : "")); // 2 hours
} else {
int mins;
if (secs == 0) { // round zero seconds to 1 minute
mins = 1;
} else {
// always round up (1-59 seconds = 1 minute)
BigDecimal secondsPerMin = new BigDecimal(60);
mins = new BigDecimal(secs).divide(secondsPerMin, RoundingMode.UP).intValue();
}
System.out.println(mins + " minute" + (mins > 1 ? "s" : ""));
}
这将打印 2 hours
持续 96 分钟,1 minute
持续 0 到 60 秒,依此类推。
要获得以秒为单位的差异,您还可以使用 org.joda.time.Seconds
class:
long secs = Seconds.secondsBetween(startTimeDate, endTimeDate).getSeconds();
Java 新 Date/Time API
Joda-Time 处于维护模式,正在被新的 APIs 取代,所以我不建议用它开始一个新项目。即使在 joda's website 它说:"Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
如果您不能(或不想)从 Joda-Time 迁移到新的 API,您可以忽略此部分。
如果您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.
如果您使用 Java 6 或 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it ).
下面的代码适用于两者。
唯一的区别是包名称(在 Java 8 中是 java.time
,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp
),但是 classes和方法names是一样的。
首先,要从纪元毫秒值中获取对应的时刻,可以使用Instant
class(无需将时区设置为UTC,因为Instant
代表一个UTC立即的)。然后,要计算差异,您可以使用 Duration
:
long startTimeDateInLong = // long millis value
long endTimeDateInLong = // long millis value
// get the corresponding Instant
Instant start = Instant.ofEpochMilli(startTimeDateInLong);
Instant end = Instant.ofEpochMilli(endTimeDateInLong);
// get the difference in seconds
Duration duration = Duration.between(start, end);
long secs = duration.getSeconds();
// perform the same calculations as above (with BigDecimal)
您还可以使用 ChronoUnit
来计算秒数的差异:
long secs = ChronoUnit.SECONDS.between(start, end);
我能找到的唯一方法是先以较小的单位获取时间,然后转换为所需的单位并对其进行舍入。因此,例如,对于提到的用例,获得四舍五入分钟的方法是这样的:
public Minutes getRoundedMinutes(DateTime dateTime1, DateTime dateTime2) {
return Minutes.minutes(
(int) round((double) secondsBetween(dateTime1, dateTime2).getSeconds() / Minutes.ONE.toStandardSeconds().getSeconds()));
}
@Test
public void should_round_minutes() throws Exception {
DateTime dateTime1 = new DateTime(2018, 1, 1, 1, 0, 0);
DateTime dateTime2 = new DateTime(2018, 1, 1, 1, 0, 29);
DateTime dateTime3 = new DateTime(2018, 1, 1, 1, 0, 30);
DateTime dateTime4 = new DateTime(2018, 1, 1, 1, 1, 1);
DateTime dateTime5 = new DateTime(2018, 1, 1, 1, 1, 31);
assertThat(getRoundedMinutes(dateTime1, dateTime2).getMinutes()).isEqualTo(0);
assertThat(getRoundedMinutes(dateTime1, dateTime3).getMinutes()).isEqualTo(1);
assertThat(getRoundedMinutes(dateTime1, dateTime4).getMinutes()).isEqualTo(1);
assertThat(getRoundedMinutes(dateTime1, dateTime5).getMinutes()).isEqualTo(2);
}
我正在使用 Joda-Time Duration
来获取两个 DateTime
:
DateTime startTimeDate = new DateTime(startTimeDateInLong, DateTimeZone.UTC);
DateTime endTimeDate = new DateTime(endTimeDateInLong, DateTimeZone.UTC);
Duration duration = new Duration(startTimeDate, endTimeDate);
我想按照以下规则转换:
0-60 seconds --> 1 minute ..
1.5 - 1 hour --> 1 hour
1.6 hour - 2 hour --> 2 hour
我正在使用 duration.toStandardHours()
,但是 96 分钟它给了 1 小时,而不是我想要 2 小时。
Duration
class 没有按照您想要的方式对值进行四舍五入。即使您得到 1 小时 59 分 59 秒 999 毫秒的持续时间,toStandardHours()
也会 return 1
.
要得到你想要的结果,你必须得到以秒为单位的总数,然后相应地操作这个值。您可以使用 java.math.BigDecimal
class 和 java.math.RoundingMode
来控制值的舍入方式:
// 96-minutes duration
Duration duration = new Duration(96 * 60 * 1000);
long secs = duration.toStandardSeconds().getSeconds();
if (secs >= 3600) { // more than 1 hour
BigDecimal secondsPerHour = new BigDecimal(3600);
int hours = new BigDecimal(secs).divide(secondsPerHour, RoundingMode.HALF_DOWN).intValue();
System.out.println(hours + " hour" + (hours > 1 ? "s" : "")); // 2 hours
} else {
int mins;
if (secs == 0) { // round zero seconds to 1 minute
mins = 1;
} else {
// always round up (1-59 seconds = 1 minute)
BigDecimal secondsPerMin = new BigDecimal(60);
mins = new BigDecimal(secs).divide(secondsPerMin, RoundingMode.UP).intValue();
}
System.out.println(mins + " minute" + (mins > 1 ? "s" : ""));
}
这将打印 2 hours
持续 96 分钟,1 minute
持续 0 到 60 秒,依此类推。
要获得以秒为单位的差异,您还可以使用 org.joda.time.Seconds
class:
long secs = Seconds.secondsBetween(startTimeDate, endTimeDate).getSeconds();
Java 新 Date/Time API
Joda-Time 处于维护模式,正在被新的 APIs 取代,所以我不建议用它开始一个新项目。即使在 joda's website 它说:"Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
如果您不能(或不想)从 Joda-Time 迁移到新的 API,您可以忽略此部分。
如果您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.
如果您使用 Java 6 或 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it
下面的代码适用于两者。
唯一的区别是包名称(在 Java 8 中是 java.time
,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp
),但是 classes和方法names是一样的。
首先,要从纪元毫秒值中获取对应的时刻,可以使用Instant
class(无需将时区设置为UTC,因为Instant
代表一个UTC立即的)。然后,要计算差异,您可以使用 Duration
:
long startTimeDateInLong = // long millis value
long endTimeDateInLong = // long millis value
// get the corresponding Instant
Instant start = Instant.ofEpochMilli(startTimeDateInLong);
Instant end = Instant.ofEpochMilli(endTimeDateInLong);
// get the difference in seconds
Duration duration = Duration.between(start, end);
long secs = duration.getSeconds();
// perform the same calculations as above (with BigDecimal)
您还可以使用 ChronoUnit
来计算秒数的差异:
long secs = ChronoUnit.SECONDS.between(start, end);
我能找到的唯一方法是先以较小的单位获取时间,然后转换为所需的单位并对其进行舍入。因此,例如,对于提到的用例,获得四舍五入分钟的方法是这样的:
public Minutes getRoundedMinutes(DateTime dateTime1, DateTime dateTime2) {
return Minutes.minutes(
(int) round((double) secondsBetween(dateTime1, dateTime2).getSeconds() / Minutes.ONE.toStandardSeconds().getSeconds()));
}
@Test
public void should_round_minutes() throws Exception {
DateTime dateTime1 = new DateTime(2018, 1, 1, 1, 0, 0);
DateTime dateTime2 = new DateTime(2018, 1, 1, 1, 0, 29);
DateTime dateTime3 = new DateTime(2018, 1, 1, 1, 0, 30);
DateTime dateTime4 = new DateTime(2018, 1, 1, 1, 1, 1);
DateTime dateTime5 = new DateTime(2018, 1, 1, 1, 1, 31);
assertThat(getRoundedMinutes(dateTime1, dateTime2).getMinutes()).isEqualTo(0);
assertThat(getRoundedMinutes(dateTime1, dateTime3).getMinutes()).isEqualTo(1);
assertThat(getRoundedMinutes(dateTime1, dateTime4).getMinutes()).isEqualTo(1);
assertThat(getRoundedMinutes(dateTime1, dateTime5).getMinutes()).isEqualTo(2);
}