I'd like to format a Period
using a pattern like YY years, MM months, DD days
. The utilities in Java 8 are designed to format time but neither period, nor duration. There's a PeriodFormatter
in Joda time. Does Java have similar utilities?
Asked
Active
Viewed 5,148 times
23

Mikhail Kholodkov
- 23,642
- 17
- 61
- 78

naXa stands with Ukraine
- 35,493
- 19
- 190
- 259
-
1No, java.time does not have a similar capability. – Ole V.V. Dec 13 '18 at 10:01
-
1https://stackoverflow.com/questions/266825/how-to-format-a-duration-in-java-e-g-format-hmmss – xingbin Dec 15 '18 at 08:10
4 Answers
16
One solution is to simply use String.format
:
import java.time.Period;
Period p = Period.of(2,5,1);
String.format("%d years, %d months, %d days", p.getYears(), p.getMonths(), p.getDays());
If your really need to use the features of DateTimeFormatter
, you can use a temporary LocalDate
, but this is a kind of hack that distort the semantic of LocalDate
.
import java.time.Period;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
Period p = Period.of(2,5,1);
DateTimeFormatter fomatter = DateTimeFormatter.ofPattern("y 'years,' M 'months,' d 'days'");
LocalDate.of(p.getYears(), p.getMonths(), p.getDays()).format(fomatter);

Ortomala Lokni
- 56,620
- 24
- 188
- 240
-
2I don’t like seeing `LocalDate` used as a hack. Why not do the same placeholder with value replacement approach using the String facilities in Java? – Basil Bourque Dec 12 '18 at 21:38
-
2I agree that distorting the semantic of `LocalDate` is not elegant and could lead to problems. – Ortomala Lokni Dec 12 '18 at 21:49
-
@BasilBourque I agree in general, but it seems to me that it's a workaround for a weakness in the JDK Api, which should allow the `DateTimeFormatter` to accept any `TemporalAmount`. – daniu Dec 15 '18 at 08:10
-
1The problem with this (that Joda solves) is that your string is not localized. – DavidW Dec 20 '18 at 14:19
4
There's no need to use String.format()
for simple string formatting. Using plain old string concatenation will be optimized by JVM:
Function<Period, String> format = p -> p.getYears() + " years, " + p.getMonths() + " months, " + p.getDays() + " days";

Oleg Cherednik
- 17,377
- 4
- 21
- 35
-
5Only wondering what would be wrong with a plain old method declaration in this case? – Ole V.V. Dec 17 '18 at 10:56
-
8Personally, I think the `String.format()` version is easier to read in this case. – Rich Dec 20 '18 at 14:59
2
public static final String format(Period period){
if (period == Period.ZERO) {
return "0 days";
} else {
StringBuilder buf = new StringBuilder();
if (period.getYears() != 0) {
buf.append(period.getYears()).append(" years");
if(period.getMonths()!= 0 || period.getDays() != 0) {
buf.append(", ");
}
}
if (period.getMonths() != 0) {
buf.append(period.getMonths()).append(" months");
if(period.getDays()!= 0) {
buf.append(", ");
}
}
if (period.getDays() != 0) {
buf.append(period.getDays()).append(" days");
}
return buf.toString();
}
}

Luk
- 2,186
- 2
- 11
- 32
-1
the proper way seems to be an intermediate LocalDate object and then calling format
date1.format(DateTimeFormatter.ofPattern("uuuu MM LLLL ee ccc"));
OR (where appropriate)
date1.format(DateTimeFormatter.ofPattern("uuuu MM LLLL ee ccc", Locale.CHINA))
this prints 1997 01 一月 07 周六
in chinese, 1997 01 January 01 Sun
in english and 1997 01 januari 07 zo
in dutch.
check out https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html under "Patterns for Formatting and Parsing" for your desired formatting.

RecurringError
- 62
- 3