javascript — Разница между Date.now(), new Date().getTime() и +new Date

спросил

Изменено 1 год, 6 месяцев назад

Просмотрено 966 раз

Я обычно использую Date.now() для получения метки времени. Но в последнее время мне пришлось создать объект Date и изучить все методы. Я обнаружил, что .getTime() возвращает то же самое, что и Date.now(). Так в чем тогда смысл getTime()? Кроме того, почему это работает +new Date <-- no () после Date и + перед new. И почему он ТАКЖЕ возвращает метку времени?

  • JavaScript
  • node.js

5

Date.now() дает вам метку времени прямо сейчас .

Date. getTime() дает вам отметку времени объекта даты, которая может представлять момент в прошлом или будущем.

+new Date — это немного запутанный способ сказать «создайте новый объект Date, затем преобразуйте его в число» (идентично new Number(new Date()) , и когда вы конвертируете Date в число, он возвращает отметку времени даты (т.е. getTime() .

Используйте # 1, если вы хотите, чтобы отметка времени была прямо в эту секунду, и используйте # 2, если вы хотите получить временную метку объекта Date , который вы получили откуда-то еще. Никогда не используйте # 3 — это может выглядеть умно, но все, что вы делаете, это пишете код, который запутает вас или кто-то другой позже

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

13

Как уже объяснялось в этом сообщении (Производительность — Date.now() против Date.getTime()), разница между Date.now() и Date.getTime() в основном связана с производительностью, в одном комментарии также говорится что Date.now() не работает в версиях Internet Explorer до IE9.

Метод с унарным плюсовым оператором, поэтому +Date.now работает, потому что унарный плюсовой оператор пытается преобразовать что-то в число. Вы можете добиться того же, используя номер (новая дата) . Скобки не нужны, потому что вы не передаете никаких аргументов.

Подробнее о том, почему это работает, см. здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя адрес электронной почты и пароль

Опубликовать как гость

Электронная почта

Требуется, но никогда не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Почему следует избегать Date.

now() для измерения длительности времени | Автор Deepal Jayasekara Фоновое изображение предоставлено: Фото Брук Кэмпбелл на Unsplash

Если вы летите между двумя аэропортами, которые находятся в двух разных часовых поясах, подсчитаете ли вы время, затраченное на перелет, проверив разницу между «настенными часами»? ‘ раз любого аэропорта?

Если ваш ответ «нет», то позвольте мне объяснить, почему вы не должны делать то же самое в своем коде, используя небольшой, но очень интересный эксперимент.

Эта статья является шестой в моей серии Advanced NodeJS , которая является продолжением моей серии о цикле событий Node.js. Вы можете найти другие статьи из серии Advanced NodeJS ниже:

  • Пересечение границ JS/C++
  • Глубокое погружение в рабочие потоки в Node.js
  • Понимание асинхронных ресурсов с помощью асинхронных хуков
  • Визуальное руководство по потокам NodeJS
  • Потоки NodeJS на практике
  • Почему вам следует избегать Date. now() для измерения длительности времени (Эта статья)

Примеры в этой статье относятся к JavaScript/Node. js, но описанные концепции действительны независимо от используемого языка.

Я бесчисленное количество раз видел, как разработчики (в том числе и я в какой-то момент) измеряли промежутки времени для метрик и ведения журналов, используя функции даты и времени. Эти функции используют так называемые «часы времени суток», и в JavaScript обычным подозреваемым, подпадающим под эту категорию, является 9.0011 Date.now()

(или конструктор Date ). Используя Date.now() , это код, который один из этих разработчиков написал бы для измерения продолжительности времени.

фрагмент 1: Как не мерить время!

Это хороший маленький код, который работает до тех пор, пока не перестанет работать.

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

  • Не все часы на всех компьютерах работают с одинаковой скоростью, некоторые могут работать быстрее или медленнее в сравнении и в конечном итоге могут отдаляются от друг от друга (как иногда делают некоторые наши настенные часы).
  • Этот « дрейф часов » может вызывать различные проблемы в распределенных системах.
  • NTP (сетевой протокол времени) — это один из сетевых протоколов, который используется для решения этой проблемы путем синхронизации часов компьютера с часами «сервера времени», который обычно показывает точное время.
  • Клиенты NTP, которые обычно поставляются с операционной системой, могут периодически получать время от настроенного сервера времени и корректировать локальные системные часы.
  • Если клиент NTP обнаружит, что местное время отличается от времени сервера времени, он может «исправить» его в зависимости от величины отклонения.
  • Такая «коррекция» времени может привести к внезапному переводу системных часов вперед или назад.
  • Функции, использующие часы «времени дня», такие как JavaScript Date.now() возвращают текущее системное время, на которое могут повлиять исправления NTP.

Теперь вы, наверное, понимаете, почему я сказал 9Фрагмент 0065 1 не сработает. Чтобы увидеть и понять это ясно, давайте перейдем к нашему небольшому эксперименту.

В этом эксперименте мы собираемся измерить время, необходимое для запуска функции doSomething() . Но мы собираемся имитировать коррекцию времени NTP, намеренно установив ложное время в начале и скорректировав время с помощью NTP во время выполнения функции doSomething() .

Вы можете найти полную реализацию примера в конце статьи. Этот пример работает только в macOS, поскольку он использует несколько команд/утилит оболочки macOS, но вы сможете легко изменить его для работы в Linux.

Измерение промежутка времени с помощью Date.now()
  • setFakeTime() устанавливает системные часы на на 1 минуту раньше фактического времени . Эта функция использует команду macOS date .
  • correctTimeNTP() использует клиентскую утилиту macOS sntp NTP для корректировки времени путем синхронизации с сервером времени time.apple.com .
  • Функция doSomething() моделирует задачу, которая занимает ~2000 мс. Мы используем setTimeout для моделирования этой задачи.

Если вы запустите приведенный выше код, он измерит время

doSomething() , затраченное с использованием Date.now() , и запишет его в стандартный вывод.…… И ЭТО ОТРИЦАТЕЛЬНО !

Неточное измерение промежутка времени с помощью Date.now()

Это совсем не то, чего ожидает разработчик!

Числовое значение, которое вы видите здесь, может зависеть от различных факторов, таких как загруженность вашего процессора, сколько времени потребовалось клиенту NTP для получения времени от сервера времени и т. д. Однако совершенно очевидно, что причина «отрицательная продолжительность времени» связана с тем, что клиент NTP скорректировал часы, переместив их назад (потому что в начале они были впереди на 1 минуту).

Следовательно, endTimeToD является более старой отметкой времени, чем startTimeToD .

Хотя этот пример является симуляцией, это может произойти в реальных системах по разным причинам (например, сервер времени по какой-то причине отправляет неверное время, время обновления клиента NTP после того, как он не работал в течение значительного времени, человек-оператор вручную меняет систему). время и т.д.)

Но важный вопрос, можем ли мы решить эту проблему? ДА. И ответ с помощью функции, которая использует монотонные часы , а не часы времени суток. Давайте читать дальше.

Монотонные часы — это просто счетчик, который начался с произвольной точки в прошлом и движется с той же скоростью, что и системные часы. Поскольку это всего лишь счетчик, монотонная отметка времени, считанная в данный момент времени, сама по себе бесполезна. Но важно то, что на монотонные часы не влияют поправки NTP. Следовательно, разница между двумя монотонными отметками времени, считанными в два разных момента времени, даст точную продолжительность времени между двумя точками.

Языки программирования обычно предоставляют функции как для монотонных, так и для дневных часов. В Node.js функции, возвращающие монотонное время:

  • ()

Давайте обновим наш эксперимент, чтобы использовать require('perf_hooks).performance.now() вместо Date.now() . Вы также можете попробовать эксперимент с process.hrtime.bigint() на досуге.

Я пропущу const { performance } = require('perf_hooks) часть следующих фрагментов для краткости.

Измерение промежутка времени с помощью require(‘perf_hooks’).performance.now()

Если вы запустите этот пример, он зарегистрирует следующий вывод (или аналогичный).

Точное измерение промежутка времени с использованием монотонных часов

Как видите, мы получаем точный результат, используя монотонное время.

Причина не получения точной 2000 мс потому, что setTimeout подчиняется определенной семантике цикла событий, которую я объяснил в предыдущей статье.

Теперь попробуем запустить оба эксперимента в одном скрипте, чтобы сравнить и измерить ошибку 1-го эксперимента.

В этом эксперименте мы запускаем 1-й и 2-й эксперименты в одном сценарии. И в дополнение к этому мы регистрируем:

  • Вывод команды sntp , которая выполняется внутри функции setFakeTime() .
  • Ошибка продолжительности, рассчитанная с использованием Date.now()

Если мы запустим приведенный выше скрипт, мы получим следующий вывод:

Промежуток времени, измеренный с использованием как часов времени суток, так и монотонных часов очень интересно! Мы можем ясно видеть разницу между продолжительностью времени, измеренной обоими подходами. И если вы внимательно посмотрите, « ошибка » длительности времени, измеренной с использованием Date. now() (-54,053 с), это почти то же число, что и NTP-клиент скорректировал время на (-54,053600 с), если вы игнорировать разницу в точности.

Это ясно указывает на то, что продолжительность времени, измеренная с помощью часов времени суток, напрямую зависит от поправок NTP.

Разве на Node.js setTimeout() и setInterval() не влияют корректировки времени NTP?

Цикл событий Node.js использует uv__hrtime для измерения времени цикла, в котором используются монотонные часы. Поэтому на функции setTimeout и setInterval корректировка времени NTP не влияет.

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

Поэтому всегда используйте функции, возвращающие монотонное время, для измерения продолжительности времени для метрик и ведения журнала.