3

I have a duration, e.g. like this:

PT-27900S = -27900000 milliseconds

and I want to convert this into a String with format (+/-HH:mm) Ich I convert the a negativ duration to String with:

final PeriodFormatter hoursAndMinutesFormatter = new PeriodFormatterBuilder()
                                                .printZeroAlways()
                                                .minimumPrintedDigits(2)
                                                .appendHours()
                                                .appendSeparator(":")
                                                .appendMinutes()
                                                .toFormatter();

I get e.g. this result:

-07:-45

but I want like this.

-07:45

Is there any possibility to format it like this?

Tiny
  • 27,221
  • 105
  • 339
  • 599
quma
  • 5,233
  • 26
  • 80
  • 146

1 Answers1

0

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:

  1. 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.

  2. 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).

  3. 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).

Community
  • 1
  • 1
Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
  • what is "The sign handling of Joda-Time is not compatible with XML-Schema." supposed to mean? Which schema / schema-version? That doesnt make much sense ... – specializt Jan 18 '16 at 11:56
  • @specializt This makes a lot of sense. A format like "-07:-45" is not allowed in XML-Schema. See [w3c-page](http://www.w3.org/TR/2012/REC-xmlschema11-2-20120405/#duration). – Meno Hochschild Jan 18 '16 at 12:08
  • @specializt I wanted to say: "PT-7H:-45M" instead of "-07:-45". – Meno Hochschild Jan 18 '16 at 12:16
  • i think there are quite a few large misconceptions here : XML SCHEMA DEFINITIONS are arbitrary and can be defined in any way, what you're referrring to is a RECOMMENDATION of ONE possible definition. In fact THOUSANDS of completely different definitions are used out there, even hybrid definitions are used side by side. There is no single "XML schema", you would have to state that this "sign-handling" of yours is not allowed with the W3C schema definition language, v1.1 - every other statement will be misleading and ... most of the time completely wrong – specializt Jan 18 '16 at 12:21
  • @specializt okay, I have added the xml-schema-version which is in my opinion the most relevant version. Other versions touching this area in a different way are exotic IMHO (I have never seen another xml-duration handling, and the javax.xml.datatype-classes are following v1.1 here). – Meno Hochschild Jan 18 '16 at 12:40
  • wrong, `javax.xml.datatype`'s follow the W3C definition at version 1.0. Also : https://en.wikipedia.org/wiki/XML_schema, in fact the W3C recommendation is the new kid on the block, the first ones go back to the 80s and beyond. – specializt Jan 18 '16 at 12:46
  • @specializt javax.xml indeed follows v1.0 (in strict sense) but that older version does not allow "PT-7H-45M", too. So no change or relevance. The core statement with respect to duration formats still stands. Of course, it is your right not to care about compatibility with w3c-recommendations (for me a standard), but I care and a lot of other people do, too. Cheers. – Meno Hochschild Jan 18 '16 at 13:01