Отметка времени в миллисекундах => дата ISO отключена на 1 миллисекунду - PullRequest
2 голосов
/ 13 апреля 2020

У меня есть метка времени в миллисекундах, которую я хочу преобразовать в строку даты ISO в UT C:

require 'time'

timestamp = 1534442471123

puts Time.at(timestamp / 1000.0).utc.strftime('%FT%T.%3NZ')

, которая выдает:

2018-08-16T18:01:11.122Z

Почему она отключена 1 миллисекунда (...122Z, а не ...123Z)?

Это из-за проблем с представлением памяти чисел с плавающей запятой?

1 Ответ

3 голосов
/ 13 апреля 2020

Хотя неточности Float, о которых вы уже знаете, играют здесь роль, в конечном счете, это «ошибка» спецификатора преобразования %N, которая хочет помешать вам отправиться в будущее. Из документации :

  The digits under the specified length are truncated to avoid
  carry up.

Другие преобразования (например, sprintf с '%.3f') были бы округлены в этом случае. Таким образом, миллисекунды вашего Time объекта на самом деле не 123, а 122.9???, который из-за %3N становится 122. Для точной обработки (под) секунд Time поддерживает целые и рациональные числа:

Time.at(*timestamp.divmod(1000), :millisecond, in: 'utc')
# or
Time.at(Rational(timestamp, 1000), in: 'utc')
Time.at(timestamp / 1000r, in: 'utc')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...