String.format打印错误的小时

时间:2015-04-17 12:56:48

标签: java timezone string.format

我使用String.format打印已用时间。这对分钟来说很有用:秒......

long millis = 330000;
String.format("%tMm%tSs", millis, millis);

...将打印05m30s。

但是,当我尝试在经过的时间内包含小时数时,小时数显示为19!起初我以为这是我的地方,但我已经尝试了以下......

long millis = 330000;
String.format(Locale.ITALY, "%tHh%tMm%tSs", millis, millis, millis);

......我仍然得到19h05m30s。

你甚至可以尝试

long millis = 0;
String.format(Locale.ITALY, "%tHh", millis);

但你仍然得到19小时。

发生了什么?

5 个答案:

答案 0 :(得分:1)

long值被视为java.util.Date,而非持续时间。这就是时区影响它的原因。您的millis值相当于代表1970年1月1日00:05:30的日期 UTC

尝试在当地时区制作相对于午夜的时间:

long millis = 330000;

System.out.printf("%THh%<tMm%<tSs%n", millis);

Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

cal.add(Calendar.MILLISECOND, (int) millis);

System.out.printf("%THh%<tMm%<tSs%n", cal);

答案 1 :(得分:1)

约达时间

Joda-Time库有一些类可以智能地处理一段时间,让你避免处理毫秒。

ISO 8601

ISO 8601标准定义了与您尝试使用的格式类似的格式。 Joda-Time库默认使用ISO 8601格式进行解析和生成此类字符串。

不要那么努力

换句话说,你工作太辛苦了。让Joda-Time 2.7在这里完成工作。

最好指定所需的时区,而不是隐式依赖JVM的当前默认时区(可能随时更改)。

使用proper time zone names。切勿使用既不标准也不唯一的3或4个字母代码。

DateTimeZone zone = DateTimeZone.forID ( "Europe/Rome" );

通过捕捉当前时刻假冒一些数据,然后退回几小时,几分钟和几秒钟。

DateTime now = DateTime.now ( zone );
DateTime then = now.minusHours(19).minusMinutes(5).minusSeconds ( 30 );

以两种方式代表一段时间。首先,时间轴上有一对固定点。第二,几个月,几天,几小时等。

Interval interval = new Interval( then, now );  // String representation defaults to the pair of date-time values displayed in ISO 8601 format.
Period period = interval.toPeriod();  // String representation defaults to ISO 8601 format of PnYnMnDTnHnMnS.

请注意,默认情况下,Period类'toString方法会生成ISO 8601标准格式的字符串,类似于您的PnYnMnDTnHnMnS。当P将日期部分与时间部分分开时,T标记开头。

转储到控制台。

System.out.println ( "interval: " + interval );
System.out.println ( "period: " + period );

跑步时。

interval: 2015-04-18T12:16:55.700+02:00/2015-04-19T07:22:25.700+02:00
period: PT19H5M30S

答案 2 :(得分:0)

来自Formatter doc

  

对于long,Long和Date,使用的时区是默认时区   对于此Java虚拟机实例。 Formatter的语言环境   将取代参数的区域设置(如果有的话)。

我猜Locale参数纯粹是为了格式而不是时间计算。

答案 3 :(得分:0)

看看这个例子:

int s = 330;
System.out.println(String.format("%d:%02d:%02d", s/3600, (s%3600)/60, (s%60)));

我使用了秒,但该示例也适用于毫秒,但您必须在示例中为每个数字添加000:)

答案 4 :(得分:-1)

检查modifiers,数小时为tl而不是tHh