Well, there is no format support in Joda-Time for the way you want to see negative durations. The nearest what I can see per documentation (indicated by the name) might be the method rejectSignedValues(). I have tested it in every possible configuration (inserted it at the begin, directly before appendMinutes()
, directly behind, with the undocumented argument false
or true
in all cases), but it does not do anything in my tests (see updated side-note).
So there are logically only two options left:
a) Write this hack:
PeriodFormatter hoursAndMinutesFormatter = new PeriodFormatterBuilder()
.printZeroAlways()
.minimumPrintedDigits(2)
.appendHours()
.appendSeparator(":")
//.rejectSignedValues(true) // no effect ?!
.appendMinutes()
.toFormatter();
long millis = -27900000;
Duration d = new Duration(millis);
Period p = d.toPeriod();
String s;
if (millis < 0) {
s = "-" + hoursAndMinutesFormatter.print(p.negated());
} else {
s = hoursAndMinutesFormatter.print(p);
}
System.out.println("Joda-Time: " + s); // -07:45
b) Alternatively switch to another library which has better support for negative durations.
=> Example for built-in XML-duration which has better sign handling but no real formatter beyond XML-Schema compatible representation (although you are free to query the single components of duration and format it with let's say java.util.Formatter
).
long millis = -27900000;
javax.xml.datatype.Duration xmlDuration =
DatatypeFactory.newInstance().newDuration(millis);
System.out.println("XML: " + xmlDuration.toString()); // -P0Y0M0DT7H45M0.000S
System.out.println(
String.format(
"%1$s%2$02d:%3$02d",
xmlDuration.getSign() < 0 ? "-" : "+",
xmlDuration.getHours(),
xmlDuration.getMinutes())); // -07:45
=> Or use my library Time4J which has a pattern-based duration formatter:
long millis = -27900000;
Duration<ClockUnit> duration = Duration.of(millis, ClockUnit.MILLIS); // create
duration = duration.with(Duration.STD_CLOCK_PERIOD); // normalization to hours and minutes
String s = Duration.formatter("-hh:mm").format(duration);
System.out.println("Time4J: " + s); // -07:45
Side notes:
The new Java-8 classes Duration
and Period
have the same sign handling as Joda-Time (preferring signs not in front but before every single component). You can see it when you watch the output of method toString()
. Any special duration formatter is not offered.
The sign handling of Joda-Time is not compatible with XML-Schema v1.1 (look especially at the section: 3.3.6.2 Lexical Mapping).
Now I have found out what the method rejectSignedValues()
is for. It is relevant for parsing only and just controls the exception behaviour (configurable via its boolean argument). However, parsing a value like "-07:45" would yield an unexpected millis-value different from your input (-22500000 != -27900000).