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?
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.
The Answer by Ole V.V. is correct, clever, and well-done. I would take it one step further.
PeriodDurationThe ThreeTen-Extra project adds functionality to the java.time classes built into Java 8 and later. Among its offerings is the PeriodDuration class, combining a Period (years-month-days) with a Duration (hours-minutes-seconds-nanos).
By the way, let me caution you about combining the two concepts. While that may seem fine intuitively, if you ponder a bit you may see it as problematic depending on your business logic.
Anyways, let’s adapt the code seen in the other Answer.
Period, adding that result to our PeriodDuration object.Duration, and add the result to our PeriodDuration object.Code:
List < String > inputs = List.of( "1m" , "5M" , "3D" , "30m" , "2h" , "1Y" , "3W" );
PeriodDuration pd = PeriodDuration.ZERO;
for ( String input : inputs )
{
String s = input.trim();
String lastLetter = s.substring( s.length() - 1 );
int codepoint = Character.codePointAt( lastLetter , 0 );
if ( Character.isUpperCase( codepoint ) )
{
String x = "P" + s;
Period p = Period.parse( x );
pd = pd.plus( p );
} else
{ // Else, lowercase.
String x = "PT".concat( s ).toUpperCase();
Duration d = Duration.parse(x );
pd = pd.plus( d );
}
}
System.out.println( "pd.toString(): " + pd );
P1Y5M24DT2H31M
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With