Ответ 1
TL;DR. Используйте microtime (false) и сохраняйте результаты в MySQL bigint как миллионные доли секунд. В противном случае вам нужно узнать все о арифметике с плавающей запятой, которая является большим жирным волосом.
Функция microtime PHP захватывает временную метку Unix (в настоящее время примерно шестнадцатеричную 50eb7c00 или десятичную цифру 1,357,609,984) от одного системного вызова и микросекундное время от другого системного вызова. Затем он превращает их в строку символов. Затем, если вы вызываете его с помощью (true), он преобразует это число в 64-битное число с плавающей запятой IEEE 745, что PHP вызывает float
.
На сегодняшний день вам нужно десять десятичных цифр слева от десятичной точки для хранения целочисленной отметки времени UNIX. Это сохранится до 2280 года н.э., когда ваши потомки начнут нуждаться в одиннадцати цифрах. Вам понадобится шесть цифр справа от десятичной точки для хранения микросекунд.
Вы не достигнете полной точности микросекунды. Большинство систем сохраняют свои подчиненные системные часы с разрешением что-то в диапазоне 1-33 миллисекунды. Он зависит от системы.
MySQL версии 5.6.4 и более поздних версий позволяют указать столбцы DATETIME(6)
, которые будут содержать даты и время до разрешения микросекунды. Если вы используете такую версию MySQL, которая абсолютно подходит для вас.
Перед версией 5.6.4 вам необходимо использовать MySQL DOUBLE
(64-разрядная плавающая точка IEEE 754) для хранения этих чисел. MySQL float
(32-разрядная плавающая точка IEEE 754) не имеет достаточного количества бит в своей мантиссе, чтобы полностью сохранить текущее время UNIX за считанные секунды.
Почему вы храните эти временные метки? Вы надеетесь сделать
WHERE table.timestamp = 1357609984.100000
или аналогичные запросы для поиска определенных элементов? Это чревато опасностью, если вы используете float или double numbers в любой точке вашей цепочки обработки (то есть, даже если вы используете microtime(true)
даже один раз). Они печально известны тем, что не достигли равных даже тогда, когда вы думали, что должны. Вместо этого вам нужно использовать что-то вроде этого. 0.001
, называемый "эпсилон" в торговле цифровой обработкой.
WHERE table.timestamp BETWEEN 1357609984.100000 - 0.001
AND 1357609984.100000 + 0.001
или что-то подобное. У вас не будет этой проблемы, если вы сохраните эти временные метки как десятичные или миллионные секунды в столбце bigint
.
64-разрядная плавающая точка IEEE имеет 53 бит мантиссы - точности. Нынешняя временная метка UNIX Epoch (секунды с 1 января по 1970 год 00: 00Z) раз один миллион использует 51 бит. Таким образом, в DOUBLE не так много дополнительной точности, если мы заботимся о младшем разряде. С другой стороны, точность не исчерпывается уже несколько столетий.
У вас нет прецедента с int64 (BIGINT). Если бы я действительно хранил микросекундные временные метки только для их заказа в MySQL, я бы пошел с DATETIME(6)
, потому что я получил бы много арифметики даты бесплатно. Если бы я делал приложение с большим объемом памяти, я бы использовал int64.