1

我有一个时间戳(64 位整数),它代表从 0 开始的纳秒数(想象它代表秒表运行了多长时间)。为了测试这一点,我使用31,740,770,222,000,008的是1 年、2 天、3 小时、4 分钟、5 秒、6 毫秒和 7 纳秒(以纳秒为单位),我想将此整数转换回年、天、小时、分钟、秒、毫秒和纳秒格式Y:D:H:M:S:m:n,所以我希望看到1:2:3:4:5:6:7. 我还希望能够选择我想要的分辨率,所以如果秒表只测量不到一小时的时间,我可以将其显示为M:S:m,并从中期待 4:5:6

下面是我使用的算法,但它根本不起作用(它返回1:31970222000008:3170222000008:50222000008:222000008:8:8)。有谁知道一种快速可靠的方法来做到这一点?我希望它在半毫秒内执行所有计算,因此秒表可以显示当前的毫秒数。

public static final byte
    YEAR        = 0b0100_0000,
    DAY         = 0b0010_0000,
    HOUR        = 0b0001_0000,
    MINUTE      = 0b0000_1000,
    SECOND      = 0b0000_0100,
    MILLISECOND = 0b0000_0010,
    NANOSECOND  = 0b0000_0001,

    RES_DEFAULT = (byte)(MINUTE | SECOND | MILLISECOND);

private static final double
    YEAR_IN_DAYS = 365.24219,
    DAY_IN_HOURS = 24,
    HOUR_IN_MINUTES = 60,
    MINUTE_IN_SECONDS = 60,
    SECOND_IN_MILLISECONDS = 1000,

    MILLISECOND_IN_NANOSECONDS = 1_000_000,
    SECOND_IN_NANOSECONDS = SECOND_IN_MILLISECONDS * MILLISECOND_IN_NANOSECONDS,
    MINUTE_IN_NANOSECONDS = MINUTE_IN_SECONDS * SECOND_IN_NANOSECONDS,
    HOUR_IN_NANOSECONDS = HOUR_IN_MINUTES * MINUTE_IN_NANOSECONDS,
    DAY_IN_NANOSECONDS = DAY_IN_HOURS * HOUR_IN_NANOSECONDS,
    YEAR_IN_NANOSECONDS = YEAR_IN_DAYS * DAY_IN_NANOSECONDS;

/**
 * Converts the given number of nanoseconds from timer 0 to a String in the format
 * {@code YYY:DDD:HH:MM:SS:mmmm}
 * where all values have leading zeroes. You can choose which values are used with the resFlags, which can be combined bitwise.
 * @param timeStamp the number of <B>nano</B>seconds away from timer 0
 * @param resFlags the flags representing which levels of resolution to return
 * @return the requested timestamp as a String
 */
public static String toString(long timeStamp, byte resFlags)
{
    return ""+
        ((resFlags & YEAR) != 0
            ? (long)(timeStamp / YEAR_IN_NANOSECONDS)
                + ((resFlags & ~YEAR) != 0
                    ? ":"
                    : "")
            : "")
        + ((resFlags & DAY) != 0
            ? (long)(timeStamp % DAY_IN_NANOSECONDS)
                + ((resFlags & ~(YEAR | DAY)) != 0
                    ? ":"
                    : "")
            : "")
        + ((resFlags & HOUR) != 0
            ? (long)(timeStamp % HOUR_IN_NANOSECONDS)
                + ((resFlags & ~(YEAR | DAY | HOUR)) != 0
                    ? ":"
                    : "")
            : "")
        + ((resFlags & MINUTE) != 0
            ? (long)(timeStamp % MINUTE_IN_NANOSECONDS)
                + ((resFlags & ~(YEAR | DAY | HOUR | MINUTE)) != 0
                    ? ":"
                    : "")
            : "")
        + ((resFlags & SECOND) != 0
            ? (long)(timeStamp % SECOND_IN_NANOSECONDS)
                + ((resFlags & (MILLISECOND | NANOSECOND)) != 0
                    ? ":"
                    : "")
            : "")
        + ((resFlags & MILLISECOND) != 0
            ? (long)(timeStamp % MILLISECOND_IN_NANOSECONDS)
                + ((resFlags & NANOSECOND) != 0
                    ? ":"
                    : "")
            : "")
        + ((resFlags & NANOSECOND) != 0
            ? (long)(timeStamp % 1_000_000)
            : "")
        ;
}
4

1 回答 1

2

对于过去一年的每个单元,您需要减去前一个单元“消耗”的部分。然后除以(不是 mod)下一个单位。像这样的东西,例如:

years = timeStamp / YEAR_IN_NANOSECONDS;
timeStamp -= years * YEAR_IN_NANOSECONDS;
days = timeStamp / DAY_IN_NANOSECONDS;
timeStamp -= days * DAY_IN_NANOSECONDS;
// hours next, etc...

几天你也可以这样做:

days = (timeStamp % YEAR_IN_NANOSECONDS) / DAY_IN_NANOSECONDS;

但是,对于每一个新的增量,它都会变得更加复杂。第一种方式对我来说通常看起来更干净。

您可能想要分解那个长长的返回语句以方便。获取您想要的数字,然后在获得所有数字后构建字符串。

于 2014-02-19T15:47:48.620 回答