Это похоже на R проблему с округлением в миллисекундах . Одно простое решение было бы добавить 0,5 мс, как предлагается там:
tt_ts <- strptime(tt[,1],"%Y-%m-%d %H:%M:%OS") + 0.0005
xts::xts(x=tt[,c(-1)], order.by=tt_ts)
# [,1]
# 2018-03-01 09:51:59.969 30755.5
# 2018-03-01 09:51:59.969 30755.0
# 2018-03-01 09:51:59.970 30755.5
# 2018-03-01 09:51:59.971 30756.0
# 2018-03-01 09:51:59.987 30756.5
# 2018-03-01 09:51:59.988 30756.5
Мы можем видеть это на простом примере:
st <- strptime("2018-03-01 09:51:59.971", "%Y-%m-%d %H:%M:%OS")
format(st, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.971"
pt <- as.POSIXct(st)
format(pt, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.970"
После преобразования в POSIXct
неверная мс. Увеличивая точность вывода, мы видим, что число с плавающей запятой, используемое для представления времени, чуть ниже требуемого значения, но R обрезает число вместо его округления:
format(pt, "%Y-%m-%d %H:%M:%OS6")
#> [1] "2018-03-01 09:51:59.970999"
Сдвиг на половину необходимой точности исправляет это.
format(pt + 0.0005, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.971"
Как правило, если x является числом с 3 десятичными цифрами, любое число в открытом диапазоне ( x - 0,0005, x + 0,0005) будет округляется до x . При усечении это будет работать для тех, кто находится в пределах [ x , x + 0,0005). Но те, которые в пределах ( x - 0,0005, x ) будут представлены как x - 0,001, как вы заметили. Если мы передвинем соответствующее число на 0,0005 перед усечением, мы говорим о диапазоне ( x , x + 0,001). Все эти числа будут усечены до x , как и хотелось.
Я исключаю очки x & pm; 0,0005, поскольку существуют разные правила их округления, и фактическое число с плавающей запятой, представляющее точку времени, будет намного ближе к желаемому значению, чем это.
РЕДАКТИРОВАТЬ: Относительно вопроса в комментариях о принятии различий: Там не должно иметь значения, добавляете ли вы полмиллисекунды или нет, если вы добавляете это в обе точки. Пример с моментом времени, который нуждается в самостоятельной корректировке:
st1 <- strptime("2018-03-01 09:51:59.971", "%Y-%m-%d %H:%M:%OS")
format(st1, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.970"
pt1 <- as.POSIXct(st1)
format(pt1, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.970"
format(pt1 + 0.0005, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.971"
И момент времени, который не нуждается в настройке:
st2 <- strptime("2018-03-01 09:51:59.969", "%Y-%m-%d %H:%M:%OS")
format(st2, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.969"
pt2 <- as.POSIXct(st2)
format(pt2, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.969"
format(pt2 + 0.0005, "%Y-%m-%d %H:%M:%OS3")
#> [1] "2018-03-01 09:51:59.969"
Разница такая же, независимо от какой-либо корректировки:
difftime(pt1, pt2, "secs")
#> Time difference of 0.001999855 secs
difftime(pt1 + 0.0005, pt2 + 0.0005, "secs")
#> Time difference of 0.001999855 secs