Странное поведение POSIX для двух близко расположенных временных строк с указанием формата и без него - PullRequest
0 голосов
/ 10 января 2019

Я не до конца понимаю поведение преобразования строк данных и времени в POSIX объекты. Например, у меня есть вектор из двух строк, представляющих дату и время. Преобразование без указания формата игнорирует часть времени и устанавливает часовой пояс IST:

as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'))
[1] "2017-03-24 IST" "2017-03-24 IST"

Но когда я указываю формат, он устанавливает другой часовой пояс и завершается с ошибкой для строки, где часы равны '2', но не, если время является вторым последним.

as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), format="%Y-%m-%d %H:%M:%OS")
[1] NA "2017-03-24 03:00:00 IDT"

Три вопроса:

  1. Почему часовой пояс отличается между двумя строками
  2. Почему, если формат не указан, игнорируется часть времени.
  3. Почему не удается преобразовать первую строку, когда указан формат?

1 Ответ

0 голосов
/ 10 января 2019
  1. Почему часовой пояс отличается между двумя строками

Как сказано в комментариях, он отличается из-за перехода на летнее время. Поскольку вы не включаете зону в вызов as.POSIXct, вы склонны ко многим проблемам. Когда это вообще возможно, будьте точны с часовым поясом. Это момент без шуток: если вы его знаете (и он не является частью строки), никогда не будет предполагать, что он будет выведен правильно. По моему опыту, это будет достаточно неправильно, чтобы быть действительно раздражающим и очень трудным для обнаружения, поиска и исправления.


  1. Почему, если формат не указан, игнорируется часть времени

Нет, хотя может выглядеть так. Это всего лишь признак того, что напечатано , а не сохранено. (Это часто встречается во многих функциях R, например, как он показывает pi только с небольшим количеством десятичных разрядов, хотя он, безусловно, хранит гораздо больше. Без этой модели «представление в сравнении с фактической точностью» консоль R была бы излишне полна десятичные разряды и все такое.)

Если я обновлю ваш код, чтобы явно включить зону:

as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel")
# [1] "2017-03-24 IST" "2017-03-24 IST"
as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel") + 1
# [1] "2017-03-24 00:00:01 IST" "2017-03-24 00:00:01 IST"

Во втором случае я добавил одну секунду ко времени, и вы видите, что время пришло. Вы можете посмотреть на внутренности, чтобы увидеть это по-другому:

dput(as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel"))
# structure(c(1490306400, 1490306400), class = c("POSIXct", "POSIXt"
# ), tzone = "Israel")
dput(as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel")+1)
# structure(c(1490306401, 1490306401), tzone = "Israel", class = c("POSIXct", 
# "POSIXt"))

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

Третий способ подтверждения - взять объекты posix «пропавшего времени» и явно распечатать что-то (что больше не POSIXct, а только для демонстрации):

a <- as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel")
a
# [1] "2017-03-24 IST" "2017-03-24 IST"
format(a, format="the time is %Y-%m-%d %H:%M:%S")
# [1] "the time is 2017-03-24 00:00:00" "the time is 2017-03-24 00:00:00"

  1. Почему не удается преобразовать первую строку, когда указан формат?

Как заметил @ Dave2e, согласно переходам на летнее время, это время "никогда не происходило".

Согласно https://www.timeanddate.com/time/change/israel/jerusalem?year=2017:

24 марта 2017 г. - начало перехода на летнее время

Когда местное стандартное время приближалось Пятница, 24 марта 2017 года, 2:00:00 утра. Часы были переведены на 1 час вперед Пятница, 24 марта 2017 г., 3:00:00 по местному летнему времени.

Я понимаю, что это означает, что часы сместились с 01:59:59 на 03:00:00, поэтому 02:**:** никогда не происходило. R говорит вам с NA, что это время не должно было произойти. Конечно, есть способы (хаки), которые вы можете сделать вывод , что это так: найти все значения NA, а затем попытаться преобразовать, используя плюс или минус час; если новое значение не NA, то вы нашли другой экземпляр, где R считает, что время невозможно. Если это все еще NA, то в строке должно быть что-то еще (дополнительные символы, другой порядок и т. Д.).

По своему опыту я не обнаружил, что эта логика когда-либо была неправильной (хотя я не уверен с уверенностью, что она безупречна), даже если она кажется раздражающей. Когда я думал, что это могло быть неправильно, я всегда находил что-то еще, что объясняло, почему я думаю, что у меня это точное время :

  • сбор данных хранится неверно TZ
  • При сборе данных не удалось сохранить TZ, и я сделал неверный вывод
  • некоторое преобразование в конвейере неправильно преобразовало время и / или зону (ы)
  • вероятно что-то еще, что я не исключил
...