将时间长度转换为适当的单位

时间:2016-08-29 22:51:42

标签: java time

我有时间,几秒钟,有可能非常大。我希望将所述时间转换为“适当的”圆形,可读格式。

我已经有了实现此目的的代码,但它效率不高(并且包含大量魔术数字):

    String readable = decayTime + " minutes";
    if(decayTime > 60)
    {
        decayTime /= 60;
        readable = decayTime + " hours";

        if(decayTime > 24)
        {
            decayTime /= 24;
            readable = decayTime + " days";

            if(decayTime > 365)
            {
                decayTime /= 365;
                readable = decayTime + " years";

                if(decayTime > 1000000)
                {
                    decayTime /= 1000000;
                    readable = decayTime + "mn years";

                    if(decayTime > 1000)
                    {
                        decayTime /= 1000;
                        readable = decayTime + "bn years"; 
                    }
                }
            }
        }

除了转换幻数之外,我个人无法想到如何让它变得更好。

我所问的基本上是什么是更好的方法,或者是否有内置的东西可以帮助?

修改:转到此处https://codereview.stackexchange.com/questions/139970/convert-length-of-time-to-appropriate-unit

3 个答案:

答案 0 :(得分:1)

您可以使用持续时间但不会转换为年。

Duration.ofSeconds(decayTime).toNanos();
Duration.ofSeconds(decayTime).toMillis();
Duration.ofSeconds(decayTime).toMinutes();
Duration.ofSeconds(decayTime).toHours();
Duration.ofSeconds(decayTime).toDays();

请参阅https://docs.oracle.com/javase/tutorial/datetime/iso/period.htmlhttps://docs.oracle.com/javase/8/docs/api/java/time/Duration.html

另一种选择是:

TimeUnit.SECONDS.toNanos(decayTime);
TimeUnit.SECONDS.toMicros(decayTime);
TimeUnit.SECONDS.toMillis(decayTime);
TimeUnit.SECONDS.toMinutes(decayTime);
TimeUnit.SECONDS.toHours(decayTime);
TimeUnit.SECONDS.toDays(decayTime);

这一年你可以使用一些黑客:

Long.parseLong(new SimpleDateFormat("YYYY").format(new Date(Duration.ofSeconds(decayTime).toMillis())));

但我强烈建议不要

答案 1 :(得分:0)

ISO 8601

仅供参考,ISO 8601标准为日期时间值定义了明智的非模糊格式。这包括represent a span of time的紧凑方式:PnYnMnDTnHnMnS

P标志着开头,T将年 - 月 - 天与小时 - 分 - 秒分开。

示例:

  • PT1H30M =一个半小时。
  • P3Y6M4DT12H30M5S =三年,六个月,四天,十二小时,三十五分五秒

java.time

Java 8及更高版本中的java.time类在解析或生成字符串以表示日期时间值时默认使用ISO 8601格式。

java.time类包含一对时间跨度的类。两者都可以解析/生成此ISO 8601格式。

  • Period多年,几个月和几天。
  • Duration表示天,小时,分钟,秒和小数秒。

显然,你的分钟到数十亿年的规模太过极端,但这确实适合科学以外更平凡的商业世界。

答案 2 :(得分:0)

其他答案对于较短的时间长度非常有用,但是没有一些丑陋的黑客,并且可能在我需要的较长时间段内,代码块不太有用。 @David Wallace使用了TreeMap

代码审核gave an answer
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

public class TimeFormatter {

    private NavigableMap<Long,String> timeUnits = new TreeMap<>();

    public TimeFormatter() {
        timeUnits.put(Long.MIN_VALUE, " is not a valid argument");
        timeUnits.put(TimeUnit.SECONDS.toSeconds(1), " seconds");
        timeUnits.put(TimeUnit.MINUTES.toSeconds(1), " minutes");
        timeUnits.put(TimeUnit.HOURS.toSeconds(1), " hours");
        timeUnits.put(TimeUnit.DAYS.toSeconds(1), " days");
        timeUnits.put(TimeUnit.DAYS.toSeconds(365), " years");
        timeUnits.put(TimeUnit.DAYS.toSeconds(365 * 1000000L), " million years");
        timeUnits.put(TimeUnit.DAYS.toSeconds(365 * 1000000L * 1000), " billion years");
    }

    public String format(long milliseconds) {
        Map.Entry<Long,String> unitBelow = timeUnits.floorEntry(milliseconds);

        int time = (int) (milliseconds / unitBelow.getKey());
        String formatted = time + unitBelow.getValue();

        if(time == 1 && unitBelow.getKey() < 1000000L) formatted = formatted.substring(0, formatted.length()-1); //Remove plural

        return formatted;
    }
}

我改变了大卫的答案,使用TimeUnit来减少魔数的数量,以及处理复数。

编辑:一些神奇的数字显然仍然存在,实际上处理更大单位所需的代码并不像我预期的那么糟糕。