3


I'm using joda-time (1.6.2) on a project and one of the things I'm doing is getting the difference between a predicted time and an actual time. Sometimes this difference is positive, sometimes negative. While the appropriate approach may be to use a Duration rather than a Period, using a PeriodFormatter to display the result led me a question about the PeriodFormatterBuilder class. As an example:

DateTime d1 = new DateTime(2011, 6, 17, 13, 13, 5, 0) ;
DateTime d2 = new DateTime(2011, 6, 17, 10, 17, 3, 0) ;

Period negativePeriod = new Period(d1, d2);
Period positivePeriod = new Period(d2, d1);

PeriodFormatter pf = new PeriodFormatterBuilder()
    .minimumPrintedDigits(2)
    .appendHours()
    .appendSuffix(":")
    .rejectSignedValues(true) // Does this do anything?
    .appendMinutes()
    .appendSuffix(":")
    .appendSeconds()
    .toFormatter();

System.out.printf("Negative Period: %s\n", pf.print(negativePeriod));
System.out.printf("Positive Period: %s\n", pf.print(positivePeriod));

The output of this is:

Negative Period: -02:-56:-02
Positive Period: 02:56:02

I understand that Period stores each component of its date and time separately, but to me, the expected behavior of the .rejectSignedValues(true) method for building a Formatter would be to only show the - sign for only the first element like:

Negative Period: -02:56:02

Am I misunderstanding the API, or is this a bug? JodaStephen? Anyone?

The work around to display what I want is not hard, but I'm just curious about the Builder approach.

Thanks,
-Manuel

Befloibent
  • 33
  • 1
  • 3
  • A negative periods like negative frequencies don't make much sense in the real world. JodaTime should take the absolute value of the difference. – Peter Lawrey Jun 17 '11 at 16:00
  • Thanks for your input, Peter, however, this is not a period as in 1/frequency. In Joda-Time, a `Period` is a difference between two points in time. Surely a difference can be greater than or less than zero. – Befloibent Jun 21 '11 at 15:36
  • I would have called that an Interval which is supported by JodaTime. A period is something recurring. – Peter Lawrey Jun 21 '11 at 15:39

2 Answers2

1

The Javadoc for rejectSignedValues says Reject signed values when parsing the next and following appended fields, ie. it only affects parsing, not printing.

Your proposal might make a useful enhancement, but there is no guarantee that all components would be positive, or all negative. This is also a valid period: P-6D8H (a mixture of positive and negative).

JodaStephen
  • 60,927
  • 15
  • 95
  • 117
  • Aha. Thanks, Stephen. You know, I read that in the Javadoc, but apparently it didn't register. RTFMC (Carefully). I'll just use a `Duration` for the difference (that's what I really want anyway), get the `standardSeconds`, check for sign, create a `Period` from the `Duration` of the abs(seconds) and build the `PeriodFormatter` based on the sign. Unless there's a better way to format `Duration`? Thanks again and keep up the great work. I'm curious how you'd create a period `P-6D8H` (+/-mixture) from two `DateTime`s I can only manage a `P6D8H` and a `P-6D-8H.` But, I'll keep working. – Befloibent Jun 21 '11 at 15:27
  • Perhaps then a suitable convention would be: a sign is carried to the next field by default, until it is explicitly reversed. I.e., `P-3D2H` would mean "three days and two hours in the past" whereas `P-3D+2H` would mean "two hours later than three days in the past". Of course I shudder at the backward incompatibility of that... – Pierre D Jul 10 '12 at 21:52
0

I solve negative like this:

 Duration dToFormat = duration;
    if (duration.getStandardMinutes() < 0) {
        dToFormat = duration.minus(duration).minus(duration);
    }

    ...

    if (duration.getStandardMinutes() < 0) {
                return "-"+pf.print(p); // leading minus
            }

and all code here in my case:

public static String durationToHHHmmFormat(Duration duration, String separator){
        if ( duration == null ) {
            return null;
        }

        Duration dToFormat = duration;
        if (duration.getStandardMinutes() < 0) {
            dToFormat = duration.minus(duration).minus(duration);
        }

        Period p = dToFormat.toPeriod();
        PeriodFormatter pf = new PeriodFormatterBuilder()
            .printZeroAlways()
            .minimumPrintedDigits(2) // gives the '01'
            .appendHours()
            .appendSeparator(separator)
            .appendMinutes()
            .toFormatter();

        if (duration.getStandardMinutes() < 0) {
            return "-"+pf.print(p); // leading minus
        }
        return pf.print(p);
    }
Dušan Salay
  • 309
  • 1
  • 12