Длина смазочного интервала - PullRequest
6 голосов
/ 07 января 2012

Каков наилучший способ получить отрезок времени, представленный interval в lubridate, в указанных единицах?Все, что я могу понять, это что-то вроде следующей грязной вещи:

> ival
[1] 2011-01-01 03:00:46 -- 2011-10-21 18:33:44

> difftime(attr(ival, "start") + as.numeric(ival), attr(ival, "start"), 'days')
Time difference of 293.6479 days

(я также добавил это как запрос функции на https://github.com/hadley/lubridate/issues/105,, предполагая, что лучшего способа нет - но возможнокто-то здесь знает об этом.)

Обновление - очевидно, функция difftime также не справляется с этим.Вот пример.

> (d1 <- as.POSIXct("2011-03-12 12:00:00", 'America/Chicago'))
[1] "2011-03-12 12:00:00 CST"
> (d2 <- d1 + days(1))  # Gives desired result
[1] "2011-03-13 12:00:00 CDT"
> (i2 <- d2 - d1)
[1] 2011-03-12 12:00:00 -- 2011-03-13 12:00:00 
> difftime(attr(i2, "start") + as.numeric(i2), attr(i2, "start"), 'days')
Time difference of 23 hours

Как я упоминаю ниже, я думаю, что один хороший способ справиться с этим - реализовать функцию /.interval, которая сначала не преобразует свой ввод в period.

Ответы [ 2 ]

10 голосов
/ 07 января 2012

Функция as.duration - это то, что предоставляет lubridate. Класс интервала представлен внутренне как количество секунд от начала, поэтому, если вы хотите количество часов, вы можете просто разделить as.numeric(ival) на 3600 или (3600 * 24) для дней.

Если вы хотите рабочие примеры функций, примененных к вашему объекту, вы должны предоставить вывод dput(ival). Я провел тестирование на объектах, созданных на странице help(duration), куда меня отправил ?interval.

 date <- as.POSIXct("2009-03-08 01:59:59") # DST boundary
 date2 <- as.POSIXct("2000-02-29 12:00:00")
 span <- date2 - date  #creates interval 
 span
#[1] 2000-02-29 12:00:00 -- 2009-03-08 01:59:59 
 str(span)
#Classes 'interval', 'numeric'  atomic [1:1] 2.85e+08
#  ..- attr(*, "start")= POSIXct[1:1], format: "2000-02-29 12:00:00"
 as.duration(span)
#[1] 284651999s (9.02y) 
 as.numeric(span)/(3600*24)
#[1] 3294.583
# A check against the messy method:
difftime(attr(span, "start") + as.numeric(span), attr(span, "start"), 'days')
# Time difference of 3294.583 days
3 голосов
/ 09 января 2012

Кен, Деление на дни (1) даст вам то, что вы хотите. Lubridate не приводит периоды к продолжительности, когда вы делите интервалы по периодам. (Хотя алгоритм поиска точного числа целых периодов в интервале действительно начинается с оценки, которая использует интервал, разделенный на аналогичное количество длительностей, что может быть тем, что вы заметили).

Конечным результатом является количество целых периодов, которые соответствуют интервалу. Предупреждающее сообщение предупреждает пользователя о том, что это оценка, поскольку в ответе будет пропущена некоторая доля периода. Не имеет смысла делать математику с долей периода, так как мы не можем изменить время на нем, если мы не конвертируем его в кратные более короткого периода - но не будет последовательного способа сделать преобразование. Например, день, который вы упомянули, будет равен 23 часам, а другие дни будут равны 24 часам. Вы думаете правильно: периоды - это попытка уважать изменения, вызванные летним временем, високосными годами и т. Д., Но они делают это только как единое целое.

Я не могу воспроизвести ошибку в вычитании, которую вы упомянули выше. Кажется, это работает для меня.

    three <- force_tz(ymd_hms("2011-03-12 12:00:00"), "") 
    # note: here in TX, "" *is* CST
    (four <- three + days(1))
    > [1] "2011-03-13 12:00:00 CDT"
    four - days(1)
    > [1] "2011-03-12 12:00:00 CST"
...