在Java中将秒转换为hh:mm:ss格式的时间

6

我希望将秒转换为HH:mm:ss时间格式,因此:

seconds = 3754 
result  = 10:25:40 

我知道传统方法是将时间除以3600得到小时等,但我想知道是否可以通过Java API实现这一点?


请检查此答案:http://stackoverflow.com/a/5500307/544983 - Juvanis
3个回答

11

使用java.util.Calendar

    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.MILLISECOND, 0);      
    calendar.set(Calendar.SECOND, 37540);
    System.out.println(new SimpleDateFormat("HH:mm:ss").format(calendar.getTime()));

每年两次,在有夏令时变更的国家/时区,这段代码会出现问题。 - Meno Hochschild
已经检查过了:clear()方法将日期重置为1970-01-01,那里可能没有夏令时的改变,因此您的代码在旧的JDK中是正确的。 - Meno Hochschild
无论如何,这是一个很好的观点。时间值始终取决于日期和时区。我已经修改了答案,以便保留当前日期(因此在DST更改日时考虑到它)。然而,问题并没有说明是否应该考虑DST,因此由提问者选择是清除(),还是将小时、分钟和毫秒字段设置为0。 - david a.
@david 谢谢你的回答。你能告诉我如何使用日历类将时间从HH:mm或HH:mm:ss转换为秒吗?谢谢。 - user523956
@david:对于56040秒和56099秒,它都给出了15:34。我期望它在56099时为我提供15:35。有什么办法可以在超过30秒时四舍五入? 我尝试过:- if (calendar.get(Calendar.SECOND) >= 30) calendar.add(Calendar.MINUTE, 1); calendar.set(Calendar.SECOND, timeInSeconds); 但是没有帮助.. - user523956
56099匹配15:34:59,所以实际上是正确的。如果您想要每30分钟增加一次分钟数,而不是在整点时增加,首先想到的事情(没有太多思考,所以可能是错误的)是calendar.set(Calendar.SECOND, 56099 + 30) - david a.

1

LocalTime

Java内置的java.time类可以实现此功能。LocalTime类表示一天中的时间,不包括日期和时区。该类包含一天中的秒数,即从一天开始计算的秒数。

LocalTime lt = LocalTime.ofSecondOfDay( 3_754L );

但是结果与您在问题中展示的不太相似。

lt.toString():01:02:34

持续时间

不要使用时间来表示经过的时间。这会导致混淆和歧义。不要使用时间类,也不要使用时间格式的字符串。

对于范围在天-小时-分钟-秒之间的经过时间,请使用Duration类。

Duration d = Duration.ofSeconds( 3_754L );

d.toString(): PT1H2M34S

这个输出是一个字符串,采用标准的ISO 8601格式生成,格式为PnYnMnDTnHnMnS,其中P表示开始,T将年月日部分与小时分钟秒钟部分分开。因此,上面看到的结果意味着“一小时,两分钟和三十四秒”。


关于java.time

java.time框架内置于Java 8及以上版本。这些类取代了老旧的遗留日期时间类,如java.util.Date, .Calendarjava.text.SimpleDateFormat

Joda-Time项目现在处于维护模式,建议迁移到java.time。

要了解更多,请参见Oracle教程。在Stack Overflow上搜索许多示例和解释。规范为JSR 310
在哪里获取java.time类? ThreeTen-Extra项目扩展了java.time的附加类。该项目是java.time可能未来添加的一个试验场。您可能会在这里找到一些有用的类,例如Interval, YearWeek, YearQuarter更多

1

更新并修正我的回答:

在我的自己的库Time4J(v1.2)中,一个基于模式的解决方案已经准备好适用于Java 6及更高版本:

Duration<?> dur = 
  Duration.of(37540, ClockUnit.SECONDS).with(Duration.STD_CLOCK_PERIOD);
String s = Duration.Formatter.ofPattern("hh:mm:ss").format(dur);
System.out.println(s); // 10:25:40

在Joda-Time中,可以使用构建器方法来实现以下代码:
PeriodFormatter f =
  new PeriodFormatterBuilder().appendHours().appendLiteral(":").appendMinutes()
  .appendLiteral(":").appendSeconds().toFormatter();
System.out.println("Joda-Time: " + f.print(new Period(37540 * 1000))); // 10:25:40

我的之前发布的解决方案是一个基于字段的变通方法(使用字段SECOND_OF_DAY),它有一个严重的缺点,即只能处理小于86400秒(一天长度)的情况。 使用旧日历代码的已接受答案也存在这个 bug,因此它不是一个真正的解决方案。 在Java-8中(包含一个新的时间库-JSR-310),也没有可用的解决方案,因为它仍然缺少格式化持续时间的可能性。不同提议的样本输出:
input = 337540 seconds (almost 4 days)
code of accepted solution => 21:45:40 (WRONG!!!)
Time4J-v1.2 => 93:45:40
Joda-Time => 93:45:40

结论是,使用外部库来解决您的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接