Format Java.Time Period/Duration (ISO 8601 Durations) To Human Readable String

April 13, 2018
format P3Y6M4D to human readable string of “three years, six months, four days”

java.time.Period supports ISO 8601 Durations, which accept the following format

  • P: duration designator (for period) placed at the start of the duration representation
  • Y: year designator that follows the value for the number of years. e.g. P1Y represent 1 year
  • M: month
  • D: day

NOTE: java.time.Period only support year, month and day.

NOTE: java.time.Duration support day and time (but not month and year), no neither Period or Duration can parse P1Y2M10DT2H30M. Probably there is a hack to mix these two together or add in some manual calculation.

NOTE: you might want to explore Joda Time which has Intervals, Durations and Periods.

I want to format P3Y6M4D to human readable string of “three years, six months, four days”.

I use the following code to convert Google Play Billing Library SkuDetails.getSubscriptionPeriod (e.g. P1W equates to one week, P1M equates to one month, P3M equates to three months, P6M equates to six months, and P1Y equates to one year)

val period = Period.parse(skuDetails.subscriptionPeriod)
// P1Y
val tokens = mutableListOf<String>()
if (period.years > 0) {
    tokens.add(period.years.let {
        if (it == 1) "1 year" else "$it years"
else if (period.months > 0) {
    tokens.add(period.months.let {
        if (it == 1) "1 month" else "$it months"
else if (period.days > 0) {
    tokens.add(period.days.let {
        if (it == 1) "1 day" else "$it days"

val periodText = tokens.joinToString(", ")

NOTE: You might want to explore Joda-Time PeriodFormatterBuilder or Apache Common Lang DurationFormatUtils.

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.