java.sql.Timestamp способ хранения NanoSeconds - PullRequest
7 голосов
/ 30 апреля 2011

Конструктор java.sql.Timestamp выглядит следующим образом:

public Timestamp(long time) {
    super((time/1000)*1000);
    nanos = (int)((time%1000) * 1000000);
    if (nanos < 0) {
        nanos = 1000000000 + nanos;     
        super.setTime(((time/1000)-1)*1000);
    }
}

Он в основном принимает время в миллисекундах, а затем извлекает последние 3 цифры и превращает его в нано.Так что для значения в миллисекундах 1304135631 421 я получаю Timestamp.getnanos () как 421000000 .Это простой расчет (добавление 6 нулей в конце) ... не кажется оптимальным.

Лучшим способом был бы конструктор Timestamp, который принимает время в наносекундах и затем вычисляет значение наносекунды из этого.

Если вы запустите приведенную ниже программу, вы увидите разницу между фактическиминаносекунды и тот, который возвращен Timestamp способ расчета наносекод.

long a = System.currentTimeMillis();
    for(;;){
        long b = System.currentTimeMillis();
        Timestamp tm = new Timestamp(System.currentTimeMillis());
        System.out.println(tm.getTime());
        System.out.println(tm.getNanos());
        System.out.println("This is actual nanos" + System.nanoTime()%1000000000);
        System.out.println("--------------------------");
        if(b-a >= 1)
            break;
    }

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

Ответы [ 4 ]

6 голосов
/ 30 апреля 2011

Время в миллисекундах не представляет время в нанослоях.Точнее, просто не может быть.Вы должны использовать Timestamp#setNanos() для установки настоящих нанос.

long timeInMillis = System.currentTimeMillis();
long timeInNanos = System.nanoTime();

Timestamp timestamp = new Timestamp(timeInMillis);
timestamp.setNanos((int) (timeInNanos % 1000000000));

// ...
2 голосов
/ 31 марта 2017

С момента введения java.time.* в java.sql.Timestamp появился новый заводской метод: Timestamp.from(Instant.now()) выполнит эту работу (с точностью до наносекунд).Существует также Timestamp.toInstant(), чтобы преобразовать его наоборот.

0 голосов
/ 12 ноября 2014

Мне нравится реализация OpenJPA TimestampHelper . Он использует статические инициализаторы, чтобы отслеживать истекшие наносекунды между вызовами, чтобы сделать отметку времени.

0 голосов
/ 25 октября 2013

Хотя это старый пост, я хотел бы добавить, что документы Timestamp действительно заявляют, что он "держит доли секунды, позволяя спецификацию доли секунды с точностью до наносекунд ». Запутывающая часть -« держать ». Сначала это кажется странным, но при правильном понимании фактически не говорит о том, что оно содержит наносекунды. value.It говорит, что он «держит» дробное значение и позволяет ему быть «точность» наносекунд. Точность следует понимать с точки зрения представления от общего количества цифр. Таким образом, это, по сути, означает, что часть на самом деле дробная (все еще миллисекунды), но умножена на 1000000, чтобы представить ее в виде наносекунд.

Принятый ответ (всегда полезный BaluC) подытоживает его.

...