3

TimeUnit.toSeconds works well when the result is > 1. However, because we're dealing with longs, if the result is between 0 and 1 exclusive, we get 0 instead. Is the a java SDK function that handles double conversions for us?

I understand that I can perform these conversion myself by multiplying or dividing by the appropriate double. However, it is error prone and does not read well. My preference is to use an existing function from the Java SDK, similar to Java's TimeUnit.

Minimal example demonstrating my situation:

import java.util.*;
import java.util.concurrent.*;
public class Main {
    public static void main(String[] args) {
        System.out.println(TimeUnit.MILLISECONDS.toSeconds(1));
    }
}

Output:

0

I want a function that handles doubles that returns 0.001

joseph
  • 2,429
  • 1
  • 22
  • 43
  • 4
    Questions asking us to recommend or find a tool or software library are off-topic for Stack Overflow as they tend to attract opinionated answers and spam – Michael Mar 13 '18 at 16:54
  • How about `TimeUnit.MILLISECONDS.toSeconds(millis * 1000) / 1000.0`? It's really not rocket science, is it? Just wrap that into your own class. – JB Nizet Mar 13 '18 at 16:58
  • 1
    @JBNizet, I actually strongly disagree. There are lots of advantages to libraries that make clear what they're doing and deal with the units for you, and IIRC there are JDK libraries in Java 8that handle time units better. – Louis Wasserman Mar 13 '18 at 17:00
  • 1
    @LouisWasserman I don't recommend writing that every time a conversion must be done. But simply wrap that in a class, i.e. make your own library. – JB Nizet Mar 13 '18 at 17:01
  • 1
    If you want it to be less error prone and read well, write your own method: `public static double toSeconds(long millis)` Yes, you’ll be doing the math yourself, but only in one place, so if you do make an error, it only needs to be fixed once. – VGR Mar 13 '18 at 17:02
  • I no longer ask for a library. Maybe there's something in the Java SDK that already does this? – joseph Mar 13 '18 at 17:03
  • @JBNizet If you look at how TimeUnit does it, you'll see that even wrapping it in your own class is error prone: http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.jsr166-mirror/jsr166/1.7.0/java/util/concurrent/TimeUnit.java – joseph Mar 13 '18 at 17:10
  • 4
    I'm not aware of any function, either in standard libraries or in an external library which does that. You'll probably have to write your own method, something like `double convertTimeUnit(long value, TimeUnit fromUnit, TimeUnit toUnit) { return fromUnit.compareTo(toUnit) > 0 ? (double) toUnit.convert(value, fromUnit) : (double) value / fromUnit.convert(1, toUnit); }` – korolar Mar 13 '18 at 17:10
  • @korolar That's good. That solution heavily reuses TimeUnit. To and from any unit will be handled. – joseph Mar 13 '18 at 17:13
  • @DodgyCodeException I just tried it and I get 1.5. `System.out.println(convertTimeUnit(1500, TimeUnit.MILLISECONDS, TimeUnit.SECONDS));` output `1.5` – joseph Mar 13 '18 at 18:25

2 Answers2

7

korolar’s suggestion is so good it deserves to be an answer and have proper formatting. It gives you approximately half of what you want. If you’re to do the multiplication or division yourself, you can at least take the number to multiply or divide by from the library enum.

public static double millisToSeconds(long millis) {
    return (double) millis / TimeUnit.SECONDS.toMillis(1);
}

Now millisToSeconds(1) gives 0.001. I agree with the comments by JB Nizet and VGR that you should wrap the calculation in a method with a nice name to keep your code well readable. If you want the method to be more general:

public static double convertTimeUnit(double amount, TimeUnit from, TimeUnit to) {
    // is from or to the larger unit?
    if (from.ordinal() < to.ordinal()) { // from is smaller
        return amount / from.convert(1, to);
    } else {
        return amount * to.convert(1, from);
    }
}

Now convertTimeUnit(1, TimeUnit.MILLISECONDS, TimeUnit.SECONDS) gives 0.001 as before, while convertTimeUnit(1, TimeUnit.SECONDS, TimeUnit.MILLISECONDS) gives 1000.0.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

Excellent! I would increment that method with add an additional check just to avoid an useless conversion to take place if the same TimeUnit is passed in both from and to parameters:

public static double convertTimeUnit(double amount, TimeUnit from, TimeUnit to) {
    // if the same unit is passed, avoid the conversion
    if (from == to) {
        return amount;
    }
    // is from or to the larger unit?
    if (from.ordinal() < to.ordinal()) { // from is smaller
        return amount / from.convert(1, to);
    } else {
        return amount * to.convert(1, from);
    }
}
Oswaldo Junior
  • 116
  • 1
  • 5