Насколько точно я должен кодировать Unix Time? - PullRequest
7 голосов
/ 14 мая 2019

Я столкнулся с этим, потому что я работаю со временем на разных платформах и, похоже, все они немного отличаются друг от друга тем, как время Unix реализовано и / или обрабатывается в их системе.Таким образом, вопрос.

Цитирование страницы Википедии по Unix Time :

Unix не имеет традиции прямого представления нецелых чисел времени Unix в виде двоичных дробей.Вместо этого времена с точностью до секунды представляются с использованием составных типов данных, которые состоят из двух целых чисел, первое из которых является time_t (неотъемлемой частью времени Unix), а второе - дробной частью временного числа в миллионных долях (вstruct timeval) или миллиардные доли (в struct timepec).Эти структуры предоставляют основанный на десятичной дроби формат данных с фиксированной точкой, который полезен для некоторых приложений и тривиален для преобразования для других.

, который, кажется, является реализацией в Go (UnixNano).Однако на практике есть много языков / платформ, которые используют миллисекунды (Java?), А также некоторые платформы используют Float (чтобы поддерживать некоторую точность), а другие в основном используют Int.


Так что если яЯ использую транспортный формат, и у меня есть только 64 бита для хранения значения времени, и не более, у меня вопрос двоякий:

  • Должен ли я кодировать его как целое число или с плавающей запятойстоимость балла?И
  • Должен ли я использовать секунды, миллисекунды или наносекунды с точностью?

Основная цель состоит в том, чтобы попытаться быть максимально точным на всех языках и платформах (без обращения кпользовательский код на каждой отдельной платформе, конечно).


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

Ответы [ 2 ]

6 голосов
/ 26 мая 2019

Зависит от требуемой точности значения времени и его максимального диапазона.

При хранении наносекунд в 64-разрядном целом числе без знака диапазон составляет около 584 лет (2 ^ 64 нс), поэтому он достаточно точный и достаточно длинный для любого практического применения.

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


Если значение времени является абсолютным моментом времени, а не продолжительностью, формат преобразования также должен определить, какую дату / время обозначает значение 0. (то есть эпоха)

Получить текущее время в UNIX-подобной системе можно, например, с помощью gettimeofday(), который возвращает структуру со значением секунд и микросекунд. Затем его можно преобразовать в одно 64-битное целое число, дающее значение в микросекундах. Время для UNIX - 1 января 1970 года, 00:00:00 UT. (Функция clock() измеряет не реальное время, а время, в течение которого процессор был активен.)

Когда значение времени для того же транспортного формата генерируется на другой платформе (например, Windows с GetSystemTime(), его необходимо будет преобразовать в ту же единицу и эпоху.


Поэтому для транспортного протокола необходимо исправить следующие вещи:

  • Единица измерения времени (мс, сша, ...) в зависимости от требуемой точности и диапазона
  • Если время является точкой времени, а не продолжительностью, Epoch (дата и время значения 0)
  • Хранится ли оно в целом числе (без знака или со знаком, если это длительность может быть отрицательной) или в виде числа с плавающей запятой
  • Порядковый номер 64-битного значения
  • Если используется плавающая точка, формат значения с плавающей точкой (обычно IEEE 754)

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

4 голосов
/ 26 мая 2019

Для максимальной переносимости и точности вы, вероятно, должны использовать тип, указанный в POSIX.Таким образом, код будет переносимым на все Unix-системы и другие операционные системы, соответствующие POSIX.

Я предлагаю использовать clock_t и clock() функцию для времени.Это имеет множество применений, включая измерение времени и расстояния между одной точкой в ​​программе и другой.Просто обязательно приведите результат к double и разделите на CLOCKS_PER_SEC впоследствии, чтобы преобразовать это время в удобочитаемый формат.

Итак, чтобы ответить на ваш вопрос:

  1. Используйте как целое число, так и значение с плавающей запятой
  2. Неопределенная точность (количество тактов между вызовами), но достаточно точная для всех некритических приложений и некоторых более важных
...