我想计算Java中两小时(HH:mm:ss)之间的时差(持续时间)。在这里,我已经阅读了关于这个主题的几个主题,但我的问题有点不同。
我也无法使用Joda-Time
。
示例:
input values: 12:03:00
00:00:00
expected output: 11:57:00
Сode:
public static void main(String[] args) throws ParseException {
Scanner sc = new Scanner(System.in);
String startTime = sc.next();
String endTime = sc.next();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
Date d1 = sdf.parse(startTime);
Date d2 = sdf.parse(endTime);
long elapsed = d2.getTime() - d1.getTime();
String hms = String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(elapsed),
TimeUnit.MILLISECONDS.toMinutes(elapsed) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(elapsed)),
TimeUnit.MILLISECONDS.toSeconds(elapsed) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(elapsed)));
if (elapsed > 0) {
System.out.println(hms);
} else {
elapsed = elapsed * (-1); //otherwise, print hours with '-'
String hms1 = String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(elapsed),
TimeUnit.MILLISECONDS.toMinutes(elapsed) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(elapsed)),
TimeUnit.MILLISECONDS.toSeconds(elapsed) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(elapsed)));
System.out.println(hms1);
}
}
结果:
expected output: 11:57:00
actual output: 12:03:00 //that's the problem
答案 0 :(得分:3)
Duration.between(
LocalTime.parse( "12:03:00" ) ,
LocalTime.parse( "23:59:59.999999999" )
).plusNanos( 1 ).withNanos( 0 )
PT11H57M
现代方法使用java.time类。
抓住的是,只有时间,没有午夜。因此,您显然打算在一天结束时使用的00:00
实际上被解释为“开始日期”。
在白天结束前只有最后一个纳秒。 LocalTime
为最后一个纳秒定义了一个常量:LocalTime.MAX
= 23:59:59.999999999
由于你只关心整秒,我们可以利用那个小数秒。如果您的结束时间恰好是00:00:00
,请替换LocalTime.MAX
。然后计算Duration
个对象。您可以添加单个纳秒,然后通过将小数秒(纳秒)设置为零来截断结果小数秒。
对于除00:00:00
以外的结束时间,数学仍然有效。添加纳秒会使您获得….000000001
秒的分数,而Duration::withNanos
会截断不需要的分数。
// This code assumes the inputs are *always* in whole seconds, without any fraction-of-second.
LocalTime start = LocalTime.parse( "12:03:00" );
LocalTime stop = LocalTime.parse( "00:00:00" );
if( stop.equals( LocalTime.MIN ) ) {
stop = LocalTime.MAX ; // `23:59:59.999999999`
}
Duration d = Duration.between( start , stop );
d = d.plusNanos( 1 ).withNanos( 0 ) ;
System.out.println( "start/stop: " + start + "/" + stop );
System.out.println( "d: " + d );
请参阅此code run live at IdeOne.com。
PT11H57M
toString
的输出是标准ISO 8601 format。 Duration
类可以解析这些字符串以及生成它们。
我强烈建议 not 表示时间范围内的时间范围,HH:MM:SS。这是模棱两可的,并且在人类阅读时经常会引起混淆。
但是如果你坚持这种格式,你必须自己构建字符串。 Duration
类缺少在其他java.time类中看到的format
方法。奇怪的是,这个类最初缺乏提取部件的方法,几天,几小时,几分钟,几秒钟。有关讨论,请参阅this Question。 Java 9带来了这样的方法,名为to…Part
。
在使用Java 8时,我建议对ISO 8601格式化输出进行字符串操作。用空字符串替换PT
。如果有M
,请用冒号替换H
。如果有S
,请用冒号替换M
,并用空字符串替换S
。如果没有S
,请将M
替换为空字符串。我相信你可以在Stack Overflow上找到这个代码。
答案 1 :(得分:1)
这里的基本缺陷是你想要两次之间的最近距离。在构建日期对象时,即使您只格式化为小时:分钟:秒仍然存储日/月/年等...对于日期12:03:00和00:00:00,它们默认为同一天,所以(午夜到中午)的差异就是你第二天没有(午夜到午夜)。您的解决方案是检查时间是否小于12(军事时间),如果是,则在当天加1。
在这里' s你是怎么做到的:
String t1 = "12:03:00";
String t2 = "00:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
Date d1 = sdf.parse(t1);
Date d2 = sdf.parse(t2);
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(d1);
c2.setTime(d2);
if(c2.get(Calendar.HOUR_OF_DAY) < 12) {
c2.set(Calendar.DAY_OF_YEAR, c2.get(Calendar.DAY_OF_YEAR) + 1);
}
long elapsed = c2.getTimeInMillis() - c1.getTimeInMillis();
答案 2 :(得分:0)
这就是你想要做的事情:
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class HourTest {
public static void main(String[] args) throws Exception {
LocalDateTime ldt1 = LocalDateTime.parse("2015-05-04T12:07:00");
LocalDateTime ldt2 = LocalDateTime.parse("2015-05-04T00:00:00");
long seconds = Math.abs(ChronoUnit.SECONDS.between(ldt1, ldt2));
String hms = String.format("%02d:%02d:%02d", seconds / 3600, (seconds / 60) % 60, seconds % 60);
// Prints 12:07:00. I tried it.
System.out.println(hms);
}
}
答案 3 :(得分:0)
您可以使用 java.time.Duration
,它以 ISO-8601 standards 为模型,并作为 JSR-310 implementation 的一部分与 Java-8 一起引入。 Java-9 引入了一些更方便的方法。
演示:
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalTime startTime = LocalTime.parse("12:03:00");
LocalTime endTime = LocalTime.parse("00:00:00");
LocalDateTime startDateTime = today.atTime(startTime);
LocalDateTime endDateTime = today.atTime(endTime);
if (startDateTime.isAfter(endDateTime)) {
endDateTime = endDateTime.with(LocalTime.MIN).plusDays(1).with(endTime);
}
Duration duration = Duration.between(startDateTime, endDateTime);
// Default format
System.out.println(duration);
// Custom format
// ####################################Java-8####################################
String formattedDuration = String.format("%02d:%02d:%02d", duration.toHours(), duration.toMinutes() % 60,
duration.toSeconds() % 60);
System.out.println(formattedDuration);
// ##############################################################################
// ####################################Java-9####################################
formattedDuration = String.format("%02d:%02d:%02d", duration.toHoursPart(), duration.toMinutesPart(),
duration.toSecondsPart());
System.out.println(formattedDuration);
// ##############################################################################
}
}
输出:
PT11H57M
11:57:00
11:57:00
从 Trail: Date Time 了解现代日期时间 API。