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 минуту раньше фактического времени . Эта функция использует команду macOSdate
. -
correctTimeNTP()
использует клиентскую утилиту macOSsntp
NTP для корректировки времени путем синхронизации с сервером времениtime.apple.com
. -
Функция doSomething()
моделирует задачу, которая занимает ~2000 мс. Мы используемsetTimeout
для моделирования этой задачи.
Если вы запустите приведенный выше код, он измерит время
, затраченное с использованием 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)
часть следующих фрагментов для краткости.
Если вы запустите этот пример, он зарегистрирует следующий вывод (или аналогичный).
Точное измерение промежутка времени с использованием монотонных часовКак видите, мы получаем точный результат, используя монотонное время.
Причина не получения точной
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 не влияет.
Если для целей мониторинга и регистрации требуется измерение продолжительности времени, всегда ожидается, что оно будет точным. Использование неправильной функции для измерения промежутков времени может привести к очень неточным результатам, как мы видели в ходе наших экспериментов.
Поэтому всегда используйте функции, возвращающие монотонное время, для измерения продолжительности времени для метрик и ведения журнала.