我怎么能把时间戳(纳秒从0)转换成Y:D: M: M: n?

时间:2021-11-14 21:29:25

I have a timestamp (64-bit integer) that represents the number of nanoseconds from 0 (imagine it representing how long a stopwatch has been running). To test this, I am using 31,740,770,222,000,008, which is 1 year, 2 days, 3 hours, 4 minutes, 5 seconds, 6 milliseconds, and 7 nanoseconds in nanoseconds, and I want to convert this integer back into years, days, hours, minutes, seconds, milliseconds, and nanoseconds in the format Y:D:H:M:S:m:n, so I expect to see 1:2:3:4:5:6:7. I also want to be able to pick and choose which resolutions I want, so if the stopwatch is only going to measure times under an hour, I could display it as M:S:m, and expect 4:5:6 from this.

我有一个时间戳(64位整数),它表示0的纳秒数(想象它表示一个秒表运行了多长时间)。为了验证这一点,我用31740770222000008年,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。

Below is the algorithm I was using, but it isn't working at all (it returns 1:31970222000008:3170222000008:50222000008:222000008:8:8). Does anyone know a quick and reliable way to do this? I want it to perform all calculations in under half a millisecond, so the stopwatch can display the current number of milliseconds.

下面是我正在使用的算法,但它根本不起作用(它返回的是1:31970222000008:3170222000008:22 2000008:8: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)
            : "")
        ;
}

1 个解决方案

#1


2  

For each unit past the year, you need to subtract off the portion "consumed" by the previous unit. Then divide (not mod) by the next unit. Something like this, for example:

对于过去一年的每一个单元,你需要减去前一个单元“消耗”的部分。然后除以下一个单位。例如:

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

For days you could also do:

好几天你也可以这样做:

days = (timeStamp % YEAR_IN_NANOSECONDS) / DAY_IN_NANOSECONDS;

But, for each new increment it will get more complicated. The first way generally seems cleaner to me.

但是,对于每一个新的增量,它将变得更加复杂。对我来说,第一种方式似乎更干净。

You might want to break up that long return statement to facilitate. Get the numbers you want, then build the string after you have them all.

你可能想要打破那个长时间的回报声明来促进。获取您想要的数字,然后在拥有它们之后构建字符串。

#1


2  

For each unit past the year, you need to subtract off the portion "consumed" by the previous unit. Then divide (not mod) by the next unit. Something like this, for example:

对于过去一年的每一个单元,你需要减去前一个单元“消耗”的部分。然后除以下一个单位。例如:

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

For days you could also do:

好几天你也可以这样做:

days = (timeStamp % YEAR_IN_NANOSECONDS) / DAY_IN_NANOSECONDS;

But, for each new increment it will get more complicated. The first way generally seems cleaner to me.

但是,对于每一个新的增量,它将变得更加复杂。对我来说,第一种方式似乎更干净。

You might want to break up that long return statement to facilitate. Get the numbers you want, then build the string after you have them all.

你可能想要打破那个长时间的回报声明来促进。获取您想要的数字,然后在拥有它们之后构建字符串。