1

0 からのナノ秒数を表すタイムスタンプ (64 ビット整数) があります (ストップウォッチが実行されている時間を表すと想像してください)。これをテストするために、31,740,770,222,000,0081年、2 日、3 時間、4 分、5 秒、6 ミリ秒、7 ナノ秒 (ナノ秒) を使用しており、この整数を年、日、時間、分に変換したいと考えています。 、秒、ミリ秒、ナノ秒の形式Y:D:H:M:S:m:nで表示されるので、1:2:3:4:5:6:7. また、必要な解像度を選択できるようにしたいので、ストップウォッチが 1 時間未満の時間しか測定しない場合は、 として表示し、これからM:S:m期待 できます4:5:6

以下は私が使用していたアルゴリズムですが、まったく機能していません ( を返します1:31970222000008:3170222000008:50222000008:222000008:8:8)。これを行うための迅速で信頼できる方法を知っている人はいますか? ストップウォッチが現在のミリ秒数を表示できるように、0.5 ミリ秒未満ですべての計算を実行したいと考えています。

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

1 年を過ぎた単位ごとに、前の単位によって「消費された」部分を差し引く必要があります。次に、(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;

ただし、新しい増分ごとに、より複雑になります。最初の方法は、一般的に私にはきれいに見えます。

簡単にするために、その長い return ステートメントを分割することをお勧めします。必要な数字を取得し、それらをすべて取得したら文字列を作成します。

于 2014-02-19T15:47:48.620 に答える