String.format prints wrong hours

I am using String.format to print the elapsed time. This works great within minutes: seconds ...

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

      

... will print 05m30s.

However, when I try to include the clock in my elapsed time, the clock shows as 19! At first I thought it was my language, but I tried the following ...

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

      

... and I am still getting 19h05m30s.

You can even try

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

      

but you still get 19 hours.

What's happening?

+3


source to share


5 answers


The value is long

treated as java.util.Date

, not duration. This is why the time zone affects it. Your millis value is equivalent to a date representing 00:05:30 January 1, 1970 UTC .

Try to make the time relative to midnight in your local time zone:



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


source


Joda time

The Joda-Time library has classes that allow you to intelligently handle a span of time while avoiding the use of milliseconds.

ISO 8601

The ISO 8601 standard defines a format similar to what you are trying to use. The Joda-Time library uses ISO 8601 formats by default to parse and create such strings.

Dont work so hard

In other words, you are working too hard. Let Joda-Time 2.7 do the job.

It is better to specify the time zone you want than to implicitly use the JVMs' actual time zone (which can change at any time).

Use correct time zone names . Never use 3 or 4 letter codes that are neither standardized nor unique.

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

      



Fake some data by capturing the current moment, then let go for hours, minutes and seconds.

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

      

Imagine a lapse of time in two ways. First, a couple of fixed points on the timeline. Secondly, several months, days, hours, etc.

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.

      

Please note that the method of Period

class toString

by default generates a line in the standard format ISO 8601, similar to yours PnYnMnDTnHnMnS

. P

marks the beginning, while T

separates the date portion from the time of day portion.

Dump for console.

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

      

At startup.

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

      

+1


source


From the Formatter Document :

For long, long and dated times, the default time zone for this instance of the Java Virtual Machine is used. The Formatter language will replace the locale of the argument (if any).

I am assuming that the Locale argument is purely for formatting and not for timing.

0


source


Take a look at this example:

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

      

I used seconds, but this example will work for miliseconds too, but you have to add 000 to each digit in the example :)

0


source


-1


source







All Articles