Skip to content
Advertisement

How to parse time based tokens in java ?(1m 1M 1d 1Y 1W 1S)

I gets following strings from FE:

1m
5M
3D
30m
2h
1Y
3W

It corresponds to 1 minute, 5 months,3 days, 30 minutes, 2 hours, 1 year, 3 weeks.

Is there mean in java to parse it?

I want to manipulate(add/minus) with Instant(or LocalDatetTime). Is there way to do it in java?

Advertisement

Answer

Period & Duration

I consider the following solution simple and pretty general (not fully general).

public static TemporalAmount parse(String feString) {
    if (Character.isUpperCase(feString.charAt(feString.length() - 1))) {
        return Period.parse("P" + feString);
    } else {
        return Duration.parse("PT" + feString);
    }
}

It seems that your date-based units (year, month, week, day) are denoted with uppercase abbreviations (Y, M, W and D) while the time-based ones (hour and minute) are lowercase (h and m). So I test the case of the last character of the string to decide whether to parse into a Period or a Duration. I exploit the fact that both of Period.parse and Duration.parse accept the letters in either case.

You wanted to add or subtract the durations to and from Instant or LocalDateTime. This works in most cases. Let’s see:

    String[] timeAmountStrings = { "1m", "5M", "3D", "30m", "2h", "1Y", "3W" };
    LocalDateTime base = LocalDateTime.of(2019, Month.MARCH, 1, 0, 0);
    for (String tas : timeAmountStrings) {
        TemporalAmount amount = parse(tas);
        System.out.println("String: " + tas + " parsed: " + amount + " added: " + base.plus(amount));

        try {
            System.out.println("Added to Instant: " + Instant.EPOCH.plus(amount));
        } catch (DateTimeException dte) {
            System.out.println("Adding to Instant didn’t work: " + tas + ' ' + dte);
        }

        System.out.println();
    }

Output:

String: 1m parsed: PT1M added: 2019-03-01T00:01
Added to Instant: 1970-01-01T00:01:00Z

String: 5M parsed: P5M added: 2019-08-01T00:00
Adding to Instant didn’t work: 5M java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Months

String: 3D parsed: P3D added: 2019-03-04T00:00
Added to Instant: 1970-01-04T00:00:00Z

String: 30m parsed: PT30M added: 2019-03-01T00:30
Added to Instant: 1970-01-01T00:30:00Z

String: 2h parsed: PT2H added: 2019-03-01T02:00
Added to Instant: 1970-01-01T02:00:00Z

String: 1Y parsed: P1Y added: 2020-03-01T00:00
Adding to Instant didn’t work: 1Y java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Years

String: 3W parsed: P21D added: 2019-03-22T00:00
Added to Instant: 1970-01-22T00:00:00Z

We see that adding to LocalDateTime works in all cases. Adding to Instant works in most cases, only we cannot add a period of months or years to it.

Advertisement