How to format a Period in Java 8 / jsr310?
Asked Answered
D

4

24

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?

Dermis answered 12/12, 2018 at 19:12 Comment(2)
No, java.time does not have a similar capability.Hemminger
#267325Brenneman
P
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);
Pleader answered 12/12, 2018 at 19:30 Comment(4)
I 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?Marthmartha
I agree that distorting the semantic of LocalDate is not elegant and could lead to problems.Pleader
@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.Ansermet
The problem with this (that Joda solves) is that your string is not localized.Accountancy
C
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";
Coparcenary answered 15/12, 2018 at 7:57 Comment(2)
Only wondering what would be wrong with a plain old method declaration in this case?Hemminger
Personally, I think the String.format() version is easier to read in this case.Saccharo
M
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();
    }
}
Maples answered 19/12, 2018 at 21:3 Comment(0)
K
-2

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.

Katzir answered 21/12, 2018 at 22:24 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.