Converting org.joda.time.Period to java.time.Period

会有一股神秘感。 提交于 2019-12-07 17:38:49

问题


I am trying to replace org.joda.time.Period with java.time.

We have the following values stored in DB.

P1M, P1Y, P1D, PT1H, PT1M

Just to parse this value,

Period monthly = ISOPeriodFormat.standard().parsePeriod(<One of the above value from DB>);

This is simple and getting Period as expected. But, now replacing with java.time is troublesome.

Because, P1D, P1M, P1Y should be parsed using the below code,

java.time.Period period = java.time.Period.parse("P1M");

And, P1H and P1D should be parsed using the below code.

Duration dailyD = Duration.parse("P1D");

So, I might need some string check also like,

if(value.startsWith("PT")) {
   // Use java.time.Duration
} else {
   // Use java.time.Period
}

Is there any better code for this logic?

Also, Finally, I will have to find the number of occurances from some startTime to till date based on the above java.time.Period or java.time.Duration.

Like, If startDateTime is 01/01/2015 08:30,

LocalDateTime startDateTime = // the above startDateTime ..

    if(value.startsWith("PT")) {
       // Use java.time.Duration
     ChronoUnit.SECONDS.between(startDateTime,curentDate)/(duration.toMillis()/1000)
    } else {

 if(value.endsWith("Y")) {
       // Use java.time.Period
ChronoUnit.YEARS.between(startDateTime,curentDate)/(period.getYears()/1000)
} else if(value.endsWith("M")){
 ChronoUnit.MONTHS.between(startDateTime,curentDate)/(period.getMonths()/1000)
}

Is there any other better way without this value parsing?

My input could have P2M, P10M, P2Y, PT15M, PT10M. It wont have the combination of both Period and time like P1MT10M. But any number of months, years or days possible.


回答1:


Java-8 does not have such a complex duration type like the class org.joda.time.Period. But you can create your own implementation of the interface TemporalAmount in a straight-forward way:

import java.time.DateTimeException;    
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalUnit;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static java.time.temporal.ChronoUnit.*;

public class SimpleDuration implements TemporalAmount {

    private static final List<TemporalUnit> SUPPORTED_UNITS =
        Collections.unmodifiableList(Arrays.asList(YEARS, MONTHS, DAYS, HOURS, MINUTES));

    private final int amount;
    private final ChronoUnit unit;

    private SimpleDuration(int amount, ChronoUnit unit) {
        this.amount = amount;
        this.unit = unit;
    }

    public static SimpleDuration of(int amount, ChronoUnit unit) {
        if (SUPPORTED_UNITS.contains(unit)) {
            return new SimpleDuration(amount, unit);
        } else {
            throw new IllegalArgumentException("Not supported: " + unit);
        }
    }

    @Override
    public long get(TemporalUnit unit) {
        if (this.unit.equals(unit)) {
          return this.amount;
        }
        return 0;
    }

    @Override
    public List<TemporalUnit> getUnits() {
        return SUPPORTED_UNITS;
    }

    @Override
    public Temporal addTo(Temporal temporal) {
        return temporal.plus(this.amount, this.unit);
    }

    @Override
    public Temporal subtractFrom(Temporal temporal) {
        return temporal.minus(this.amount, this.unit);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof SimpleDuration) {
            SimpleDuration that = (SimpleDuration) obj;
            return this.unit == that.unit && this.amount == that.amount;
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return this.unit.hashCode() + 37 * Integer.hashCode(this.amount);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        if (this.amount < 0) {
            sb.append('-');
        }
        sb.append('P');
        if (this.unit.isTimeBased()) {
            sb.append('T');
        }
        sb.append(Math.abs(this.amount));
        switch (this.unit) {

            case YEARS :
                sb.append('Y');
                break;

            case MONTHS :
                sb.append('M');
                break;

            case DAYS :
                sb.append('D');
                break;

            case HOURS :
                sb.append('H');
                break;

            case MINUTES :
                sb.append('M');
                break;

            default :
                throw new UnsupportedOperationException(this.unit.name());
        }
        return sb.toString();
    }

    public static SimpleDuration parse(String input) {
        int len = input.length();
        int index = 0;
        boolean negative = false;
        if (len > 0 && input.charAt(0) == '-') {
            negative = true; // for XML-Schema (not for ISO-8601)
            index++;
        }
        if (len >= 3 && input.charAt(index) == 'P') {
            boolean timeBased = (input.charAt(index + 1) == 'T');
            char last = input.charAt(len - 1);
            ChronoUnit unit;
            switch (last) {

                case 'Y' :
                    unit = YEARS;
                    break;

                case 'M' :
                    unit = (timeBased ? MINUTES : MONTHS);
                    break;

                case 'D' :
                    unit = DAYS;
                    break;

                case 'H' :
                    unit = HOURS;
                    break;

                default :
                    throw new DateTimeException(
                        "Unknown unit symbol found at last position: " + input
                    );
            }
            if (unit.isTimeBased() != timeBased) {
                throw new DateTimeException("Invalid XML-Schema-format: " + input);
            }
            try {
              int amount =
                Integer.parseInt(
                  input.substring(index).substring(timeBased ? 2 : 1, len - 1 - index));
              if (amount < 0) {
                throw new DateTimeException(
                  "XML-Schema does not allow negative amounts inside: " + input);
              }
              return SimpleDuration.of(negative ? -amount : amount, unit);
            } catch (NumberFormatException ex) {
                throw new DateTimeException("Invalid XML-Schema-format: " + input, ex);
            }
        }
        throw new DateTimeException("Cannot parse: " + input);
    }

    public static void main(String... args) {
        System.out.println(parse("-PT10M")); // -PT10M
    }
}


来源:https://stackoverflow.com/questions/47217098/converting-org-joda-time-period-to-java-time-period

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!