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.
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.
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)
: "")
;
}