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?
source to share
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);
source to share
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
source to share
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.
source to share