public final class Duration { public static final Duration ZERO = new Duration(0, 0); static final int MINUTES_PER_HOUR = 60; static final int SECONDS_PER_MINUTE = 60; static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; static final long NANOS_PER_SECOND = 1000_000_000L; private final long seconds; private final int nanos; public Duration(long seconds, int nanos) { this.seconds = seconds; this.nanos = nanos; } @Override public String toString() { if (this == ZERO) { return "PT0S"; } long hours = seconds / SECONDS_PER_HOUR; int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE); int secs = (int) (seconds % SECONDS_PER_MINUTE); StringBuilder buf = new StringBuilder(24); buf.append("PT"); if (hours != 0) { buf.append(hours).append('H'); } if (minutes != 0) { buf.append(minutes).append('M'); } if (secs == 0 && nanos == 0 && buf.length() > 2) { return buf.toString(); } if (secs < 0 && nanos > 0) { if (secs == -1) { buf.append("-0"); } else { buf.append(secs + 1); } } else { buf.append(secs); } if (nanos > 0) { int pos = buf.length(); if (secs < 0) { buf.append(2 * NANOS_PER_SECOND - nanos); } else { buf.append(nanos + NANOS_PER_SECOND); } while (buf.charAt(buf.length() - 1) == '0') { buf.setLength(buf.length() - 1); } buf.setCharAt(pos, '.'); } buf.append('S'); return buf.toString(); } }