1

How to parse String expressing time (containing double and timeunit suffix (ms/ns/ps/picosecond(s)/us/fs/msec/ miliseconds etc... )) into double second.

E.g. Input String

"1.23 ms"
"0.98 ns"
"33 s"

Output double:

0.00123
0.0000000098
33.0

Thanks

Witold Kaczurba
  • 9,845
  • 3
  • 58
  • 67

5 Answers5

3

It could be done using a regular expression to extract the value and the unit as next:

Pattern pattern = Pattern.compile("(\\d+(?:\\.\\d+)?) (s|ms|us|ns|ps|fs)");

List<String> values = Arrays.asList(
    "1.23 ms", "0.98 ns", "33 s", "1.3 us", "20.5 ps", "4.5 fs"
);

values.forEach(
    value -> {
        Matcher matcher = pattern.matcher(value);
        if (matcher.find()) {
            // Convert the value into a double
            double result = Double.valueOf(matcher.group(1));
            double factor;
            // Convert the unit to a factor
            switch (matcher.group(2)) {
                case "ms" :
                    factor = Math.pow(10.0, -3.0);
                    break;
                case "us" :
                    factor = Math.pow(10.0, -6.0);
                    break;
                case "ns" :
                    factor = Math.pow(10.0, -9.0);
                    break;
                case "ps" :
                    factor = Math.pow(10.0, -12.0);
                    break;
                case "fs" :
                    factor = Math.pow(10.0, -15.0);
                    break;
                default:
                    factor = 1.0;
                    break;
            }
            // Apply the factor
            result *= factor;
            System.out.printf("%s = %s seconds%n", value, result);
        }
    }
);

Output:

1.23 ms = 0.00123 seconds
0.98 ns = 9.800000000000001E-10 seconds
33 s = 33.0 seconds
1.3 us = 1.3E-6 seconds
20.5 ps = 2.05E-11 seconds
4.5 fs = 4.5000000000000005E-15 seconds
Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
1

A simple code like this should do the trick.

private double convertExpression(String str) throws Exception{
    String []stringArr = str.split(" ");
    if(stringArr.length <= 1){
        throw new Exception("Incorrect format");
    }

    String unit = stringArr[1];
    String stringVal = stringArr[0];
    double intVal = Double.parseDouble(stringVal);

    switch(unit){
    case "ms":
        return intVal/1000;
    case "ns":
        return intVal/10e9;
    case "s":
        return intVal;
    }
    return 0;
}

If your need is simple, I would suggest you building it in as part of your code.

Jerin Joseph
  • 1,087
  • 9
  • 17
1

Thought about deleting the answer but I feel editing and making it correct with additional information may make more sense.

Yes its correct. JODA API does not support precisions beyond milliseconds. Found another stackoverflow link and perusing it I found that moving to java.time api from Java 8 should be the right decision.

I've just checked their official website which itself suggests moving to Java 8 based java.time (JSR-310) in future.

Here is another link that would help you understand more on the differences in Java 8's based Date/Time api with JODA

If you need calculations based on precisions with milliseconds and are using JDK versions prior to Java 8, then you can try JODA.

Community
  • 1
  • 1
Kamal Kunjapur
  • 8,547
  • 2
  • 22
  • 32
  • @NicolasFilotto - Well I apologise, I have updated my answer though after doing additional research. I am hoping my answer would be unaccepted soon. – Kamal Kunjapur Oct 20 '16 at 08:59
  • The java.time classes *do* handle nanoseconds. And for prior to Java 8, use the ThreeTen-Backport project rather than Joda-Time. Joda-Time project is in maintenance mode, with the team advising migration to the java.time classes. – Basil Bourque Oct 20 '16 at 09:08
  • @BasilBourque ok for nano but what about pico and micro ? it doesn't seem to be the case, doesn't it? – Nicolas Filotto Oct 20 '16 at 09:15
  • 1
    Microseconds and milliseconds fit within nanoseconds. Picoseconds is absurdly small and not handled by any conventional database or library that I've heard of, nor any computer hardware I've heard of. – Basil Bourque Oct 20 '16 at 09:20
  • @BasilBourque so even less femtosecond which is a good proof that joda and java.time cannot fit with the OP requirements – Nicolas Filotto Oct 20 '16 at 09:25
  • @NicolasFilotto I never proposed those libraries as an Answer to the Question. I was correcting statements made by others. – Basil Bourque Oct 20 '16 at 09:50
0

You can use the TimeUnit class to convert between different measurements of time.

However, you'll need to parse the string to determine the numerical value and the units.

It's not as simple as parsing the string into a double because in this case you're also converting it into seconds rather than keeping the original unit.

Brion
  • 746
  • 3
  • 10
0

In this specific example I would use Regular Expressions. You can use RegEx to extract the value from the string as well as the unit so you can handle it accordingly.

The following should work: (\d+(?:\.\d+)?)\s?(\w?s)

The first capture group would provide the decimal part, and the second capture group would provide the unit (ns / ms / s). You can store the first capture group as a double and the second as a string and perform mathematical operations on the double based on the unit obtained. If it's ns then x10^-9, et cetera.

Alternatively, a more simple but less flexible solution would be to split the string based on spaces and then use the first value in the resultant array as a double and the second as a unit. This wouldn't work if you removed the space in the string, however. I prefer the RegEx solution as you know that if a match is found then the first capture group will contain a value and the second a unit.

If you're interested in the RegEx solution then I will break it down here:

(\d+(?:\.\d+)?)\s?(\w?s)

The ( indicates the start of a capturing group The \d+ means that it is getting one or more decimal value The (?: indicates the start of a non-capturing group The \. means that it is looking for a dot The ) indicates the end of a group (capturing or non-capturing) The ? means 'one or none of this' The \s? means one or more space The \w? means one or more letter The s means it is looking for an s

In summary, it is looking for a decimal value, followed by an optional space character, then any letter and an 's'. This means it would accept any of the following:

5.00ms

5.00 s

5.10 ns

5.1259 fs

241.015552ps

1 s

It would not accept:

12 wpwa

12a

pan

511.2012wprpwaroawroaroas

It would not accept the final one as the unit has to be two characters at most - one to designate how small, such as m or n, and another to state that it is in seconds (s). If you were to decide that you would want any text after the number to show up in order to support text like "512.032 millis" then you can change the final (\w?s) to (\w*s) in the statement I provided.

VortixDev
  • 965
  • 1
  • 10
  • 23