如何在Java中以hh:mm:ss.SSS格式格式化经过的时间间隔?
我正在制作秒表,使用Java的SimpleDataFormat将毫秒数转换为一个漂亮的“hh:mm:ss:SSS”格式。问题是小时字段中总是有一些随机数。以下是我使用的代码:如何在Java中以hh:mm:ss.SSS格式格式化经过的时间间隔?,java,time,simpledateformat,Java,Time,Simpledateformat,我正在制作秒表,使用Java的SimpleDataFormat将毫秒数转换为一个漂亮的“hh:mm:ss:SSS”格式。问题是小时字段中总是有一些随机数。以下是我使用的代码: public static String formatTime(long millis) { SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss.SSS"); String strDate = sdf.format(millis); retu
public static String formatTime(long millis) {
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss.SSS");
String strDate = sdf.format(millis);
return strDate;
}
如果我去掉hh部分,它就可以正常工作了。否则,在hh部分中,即使传入的参数(毫秒数)为零,它也会显示一些随机值,如“07”
但是我对SimpleDateFormat类知之甚少。谢谢您的帮助。格式根据您的本地时区而定,因此如果您超过0,它将假定为0 GMT,然后在您的本地时区中转换它。下面是发生的情况。当你通过毫秒,这个数字是相对于1970年1月1日。当您传递0时,它将获取该日期并将其转换为您的本地时区。如果你在中心时间,那正好是晚上7点。如果你运行这个,那么一切都是有意义的
new SimpleDateFormat().format(0) => 12/31/69 7:00 PM
编辑,我想你要做的是得到经过的时间。为此,我建议使用已经做得很好的。你做的事情
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendHours()
.appendSuffix(" hour", " hours")
.appendSeparator(" and ")
.appendMinutes()
.appendSuffix(" minute", " minutes")
.appendSeparator(" and ")
.appendSeconds()
.appendSuffix(" second", " seconds")
.toFormatter();
String formattedText = formatter.print(new Period(elapsedMilliSeconds));
最新的JDK内置了对所需操作的支持,其中包含一个鲜为人知的类,名为TimeUnit
。
您要使用的是使用间隔
SimpleDataFormat
只做它听起来像做的事情,它格式化java.util.Date
的实例,或者在您的例子中,它将long
值转换为java.util.Date
的上下文,它不知道如何处理间隔,这显然是您正在使用的
您可以很容易地做到这一点,而不必求助于像JodaTime这样的外部库
import java.util.concurrent.TimeUnit;
public class Main
{
private static String formatInterval(final long l)
{
final long hr = TimeUnit.MILLISECONDS.toHours(l);
final long min = TimeUnit.MILLISECONDS.toMinutes(l - TimeUnit.HOURS.toMillis(hr));
final long sec = TimeUnit.MILLISECONDS.toSeconds(l - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min));
final long ms = TimeUnit.MILLISECONDS.toMillis(l - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min) - TimeUnit.SECONDS.toMillis(sec));
return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
}
public static void main(final String[] args)
{
System.out.println(formatInterval(Long.parseLong(args[0])));
}
}
输出的格式如下
13:00:00.000
这是我所做的Joda工作的第一部分,它似乎比JDK支持更乏味。请求格式的Joda实现(对零字段进行一些假设)是:
下面是我如何做到这一点的,仅使用标准JDK(这将通过将
StringBuilder
更改为StringBuffer
,在Java 1.1中就可以实现):
静态公共字符串格式millis(long val){
StringBuilder buf=新StringBuilder(20);
字符串sgn=“”;
if(val1){
int pad=(dgt-1);
对于(长xa=val;xa>9&&pad>0;xa/=10){pad--;}
对于(int xa=0;xa使用普通Java日历的时间间隔长达一天(24小时),请参见我对问题的回答:一种较短的方法是在以下情况下使用该类:
为什么不是这个
public static String GetFormattedInterval(final long ms) {
long millis = ms % 1000;
long x = ms / 1000;
long seconds = x % 60;
x /= 60;
long minutes = x % 60;
x /= 60;
long hours = x % 24;
return String.format("%02d:%02d:%02d.%03d", hours, minutes, seconds, millis);
}
变体:最多24小时
对于小于24小时的运行时间,简单的格式化。超过24小时,代码将只显示第二天的小时数,而不会将运行的日期添加到小时数中
public static String formatElapsedTime(long milliseconds) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf.format(milliseconds);
}
示例代码中缺少功能:
- 用“UTC”消除时区
- 使用24小时格式“HH”
变体:超过24小时
这是另一种方法。完全独立且完全向后兼容。天数不限
private static String slf(double n) {
return String.valueOf(Double.valueOf(Math.floor(n)).longValue());
}
public static String timeSpan(long timeInMs) {
double t = Double.valueOf(timeInMs);
if(t < 1000d)
return slf(t) + "ms";
if(t < 60000d)
return slf(t / 1000d) + "s " +
slf(t % 1000d) + "ms";
if(t < 3600000d)
return slf(t / 60000d) + "m " +
slf((t % 60000d) / 1000d) + "s " +
slf(t % 1000d) + "ms";
if(t < 86400000d)
return slf(t / 3600000d) + "h " +
slf((t % 3600000d) / 60000d) + "m " +
slf((t % 60000d) / 1000d) + "s " +
slf(t % 1000d) + "ms";
return slf(t / 86400000d) + "d " +
slf((t % 86400000d) / 3600000d) + "h " +
slf((t % 3600000d) / 60000d) + "m " +
slf((t % 60000d) / 1000d) + "s " +
slf(t % 1000d) + "ms";
}
私有静态字符串slf(双n){
返回字符串.valueOf(Double.valueOf(Math.floor(n)).longValue());
}
公共静态字符串时间跨度(长时间inms){
double t=double.valueOf(timeInMs);
如果(t<1000d)
返回slf(t)+“ms”;
如果(t<60000d)
返回slf(t/1000d)+“s”+
slf(t%1000d)+“ms”;
如果(t<3600000d)
返回slf(t/60000d)+“m”+
slf(t%60000d)/1000d)+“s”+
slf(t%1000d)+“ms”;
如果(t<86400000d)
返回slf(t/3600000d)+“h”+
slf(t%3600000d)/60000d)+“m”+
slf(t%60000d)/1000d)+“s”+
slf(t%1000d)+“ms”;
返回slf(t/86400000d)+“d”+
slf(t%86400000d)/3600000d)+“h”+
slf(t%3600000d)/60000d)+“m”+
slf(t%60000d)/1000d)+“s”+
slf(t%1000d)+“ms”;
}
回顾其他答案,我想出了这个函数
public static String formatInterval(final long interval, boolean millisecs )
{
final long hr = TimeUnit.MILLISECONDS.toHours(interval);
final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60;
final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60;
final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000;
if( millisecs ) {
return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
} else {
return String.format("%02d:%02d:%02d", hr, min, sec );
}
}
这个方法实际上是有效的,但似乎我正在调整方法的意图:-)
对于那些真正了解这一原理的人,您可能会发现一些注意事项
java.time.Duration
表示未附加到时间线的时间跨度(以小时-分钟-秒为刻度)的适当类为。对于年-月-天的刻度,请使用
ISO 8601格式
我建议您避免使用HH:MM:SS的时间格式报告时间跨度。我已经看到,在现实世界的商业应用程序中,固有的模糊性会导致误解和混乱
报告此类值有一个标准,具体如下:PnYnMnDTnHnMnS
。p
标记开始,而T
将任何年-月-日部分与任何时-分-秒部分分开
java.time类在解析/生成字符串时默认使用ISO 8601标准格式。这包括Duration
类
Duration d = Duration.ofMillis( 5_025_678L ) ;
String output = d.toString() ;
看这个
PT1H23M45.678S
这些ISO 8601字符串可以被解析和生成
Duration d = Duration.parse( "PT1H23M45.678S" ) ;
时间格式
但是如果您坚持在持续时间中使用每日时间格式,您可以通过调用duration
对象上的to…Part
方法来组合这样一个sting
Duration d = Duration.ofMillis( 5_025_678L ) ;
String output = d.toHoursPart() + ":" + d.toMinutesPart() + ":" + d.toSecondsPart() + "." + TimeUnit.NANOSECONDS.toMillis( d.toNanosPart() ) ;
1:23:45.678
或者我们可以滥用LocalTime
类来创建字符串
Duration d = Duration.ofMillis( 5_025_678L ) ;
long nanoOfDay = d.toNanos() ;
LocalTime localTimeBogus = LocalTime.ofNanoOfDay( nanoOfDay ) ;
String output = localTimeBogus.toString() ;
同样,你可以看到这一点
01:23:45.678
可以在DATUUTILS类中使用或方法.< /P>从中我们可以推断出你位于美国中部某个地方。使用24H格式<代码> HH>代码>代替<代码> HH。消除时区<代码> SDF.StimeTimeStand(TimeZeal.GETTimeZONE(UTC));
。请参阅下面的答案。类似问题是的,这就是实际情况。夏令时,所以CDT,而不是EDT我同意,SimpleDataFormat的设计目的不是格式化经过的时间。更容易编写自己的格式化程序或使用Joda格式化程序
public static String formatTime(long millis) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
String strDate = sdf.format(millis - 3600000);
return strDate;
}
LocalTime // Represents a time-of-day, without date and without time zone.
.ofNanoOfDay( // Convert a count of nanoseconds into a time-of-day in a generic 24-hour day, ignoring real-world anomalies such as Daylight Saving Time (DST).
Duration // Class that represents a span-of-time not attached to the timeline.
.of( milliseconds ) // Parse your count of milliseconds as a span-of-time.
.toNanos() // Extract total number of nanoseconds in this span-of-time.
) // Returns a `LocalDate` object.
.toString() // Generate text in standard ISO 8601 format for a time-of-day (*not* recommended by me).
Duration d = Duration.of( milliseconds ) ;
Duration d = Duration.ofMillis( 5_025_678L ) ;
String output = d.toString() ;
Duration d = Duration.parse( "PT1H23M45.678S" ) ;
Duration d = Duration.ofMillis( 5_025_678L ) ;
String output = d.toHoursPart() + ":" + d.toMinutesPart() + ":" + d.toSecondsPart() + "." + TimeUnit.NANOSECONDS.toMillis( d.toNanosPart() ) ;
Duration d = Duration.ofMillis( 5_025_678L ) ;
long nanoOfDay = d.toNanos() ;
LocalTime localTimeBogus = LocalTime.ofNanoOfDay( nanoOfDay ) ;
String output = localTimeBogus.toString() ;
org.apache.commons.lang.time.DurationFormatUtils.formatDuration(stopWatch.getTime(), "HH:mm:ss")