quma
quma

Reputation: 5743

JodaTime PeriodFormatter

I have the following PeriodFormatter:

PeriodFormatter periodFormatter = new PeriodFormatterBuilder().printZeroAlways().minimumPrintedDigits(2).appendHours().appendSeparator(":")
        .appendMinutes().rejectSignedValues(false).maximumParsedDigits(2).toFormatter();

and if I parse e.g. -03:00 (three hours):

final Duration hoursDuration = periodFormatter.parsePeriod(hours)

but if I parse e.g. -00:43 (45 minutes) than I get a positiv duration because the right format would be -00:-43.

My question now would be it there is a possibility with periodFormatter.

Upvotes: 0

Views: 696

Answers (1)

Meno Hochschild
Meno Hochschild

Reputation: 44071

First I make your code compilable:

PeriodFormatter periodFormatter = 
    new PeriodFormatterBuilder().printZeroAlways().minimumPrintedDigits(2)
    .appendHours().appendSeparator(":")
    .appendMinutes().rejectSignedValues(false).maximumParsedDigits(2).toFormatter();
Period p1 = periodFormatter.parsePeriod("-03:00"); // PT-3H
System.out.println(p1);
Period p2 = periodFormatter.parsePeriod("-00:43"); // PT43M
System.out.println(p2);

Explanation for the observed behaviour:

Joda-Time handles the signs of any period in a counter-intuitive way since the very beginning. Signs are never related to the whole period but only to the single distinct components of a period.

  • First case "-03:00" => Only the hour component is negative (and minutes are zero).
  • Second case "00:43" => The hour component is zero so the sign has no effect while the minute component is positive because it is not directly preceded by a negative sign.

The opinions about this behaviour are in dissent. While the Joda-team seems to consider this as enhancement and useful feature other people like me find it terrible. For example, it is possible to construct a period as P1M-30D. Is such a period positive, negative or zero? We don't really know. And the result is that a period looses the property to be like the length of a directed vector on the timeline (what is characteristic for a duration).

As far as I know there is no chance to change this behaviour in Joda-Time. If you want to parse "-00:43" as -PT43M then consider following options:

a) Manual workaround:

String input = "-00:43";
boolean negative = input.charAt(0) == '-';
Period p3 = periodFormatter.parsePeriod(input.replace("-", ""));
if (negative) {
    p3 = p3.negated();
}
System.out.println(p3); // PT-43M

b) Using my library Time4J:

This is rather a cannon for solving your concrete problem but otherwise it is worth a look because the possibilities to normalize, format or parse any duration are overwhelming. Time4J rejects mixed signs so the sign can only be in front of the whole duration.

Duration<ClockUnit> d = Duration.formatter(ClockUnit.class, "-hh:mm").parse(input);
System.out.println(d); // -PT43M

Upvotes: 1

Related Questions