2014-02-19 3 views
1

У меня есть метка времени (64-разрядное целое число), которая представляет количество наносекунд от 0 (представьте себе, как долго работает секундомер). Чтобы проверить это, я использую , то есть 1 year, 2 days, 3 hours, 4 minutes, 5 seconds, 6 milliseconds, and 7 nanoseconds in nanoseconds, и я хочу преобразовать это целое обратно в годы, дни, часы, минуты, секунды, миллисекунды и наносекунды в формате Y:D:H:M:S:m:n, поэтому я ожидаю увидеть 1:2:3:4:5:6:7. Я также хочу, чтобы иметь возможность выбирать, какие разрешения я хочу, поэтому, если секундомер будет только измерять время менее часа, я мог бы отображать его как M:S:m и ожидать от этого 4:5:6.Как преобразовать временную метку (наносекунды от 0) в Y: D: H: M: S: m: n?

Ниже приведен алгоритм, который я использовал, но он вообще не работает (он возвращает 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) 
      : "") 
     ; 
} 
+0

Ваш номер теста неверен. Если он содержит 6 миллисекунд и 7 наносекунд, последние цифры должны быть 006 000,007. – interjay

+0

@interjay вы учли год 365.24219 года? – Supuhstar

+1

А, я думал, вы будете использовать 365 дней в году. Даже вольфрам альфа, который вы связываете, использует 365 дней. – interjay

ответ

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; 

Но, для каждого нового прироста будет получить сложнее. Первый способ, как правило, кажется мне более чистым.

Возможно, вам захочется разбить этот длинный оператор возврата для облегчения. Получите нужные числа, затем создайте строку после того, как у вас есть все.

Смежные вопросы