Рассчитайте разницу во времени только по месяцам и дням - PullRequest
0 голосов
/ 16 декабря 2018

Я хотел бы рассчитать разницу во времени, учитывая ТОЛЬКО дни и месяцы.Например:

> as.Date("2018-12-15")-as.Date("2018-12-16")
Time difference of -1 days

> as.Date("2008-12-15")-as.Date("2018-12-16")
Time difference of -3653 days

Я хочу, чтобы они оба вернули -1.

Редактировать: високосные годы не должны учитываться, так как нам просто нужно приближение, а возвращаемое значение не нужнобудь точным.

Ответы [ 4 ]

0 голосов
/ 17 декабря 2018

Другим решением может быть извлечение только даты года из каждой даты, а затем выполнение математических операций, особенно если високосные годы важны .

Например,DoY для следующего:

DayOfYear(2020, 12, 15) = 350   # leap year
DayOfYear(2018, 12, 15) = 349
DayOfYear(2016, 12, 15) = 350   # leap year
DayOfYear(2011, 12, 16) = 350

Вы можете найти множество предложений о том, как получить DoY из извлечения номера дня года из дат и Как конвертировать POSIXдата в день года в R? .

0 голосов
/ 16 декабря 2018

Вопрос недостаточно четко определен для случая, когда даты колеблются в конце февраля, и один год является високосным, а если нет, то, игнорируя это, мы можем заменить год в каждой дате високосным годом, если любая из них являетсяв противном случае високосный год (2000 год) и не високосный год (1999 год), а затем вычтите:

library(lubridate)

d1 <- "2008-12-15"
d2 <- "2018-12-16"

yr <- 1999 + (leap_year(as.Date(d1)) || leap_year(as.Date(d2)))
as.Date(sub("....", yr, d1)) - as.Date(sub("....", yr, d2))
## Time difference of -1 days

ДОБАВЛЕНО

В комментарии автор указал, что мы можем игнорировать возникшие проблемывисокосными годами.В этом случае мы можем просто выбрать високосный год в качестве даты для замены, чтобы он всегда возвращал ответ.Мы делаем это ниже.Нам больше не нужно использовать lubridate для проверки того, являются ли даты високосными годами.

as.Date(sub("....", 2000, d1)) - as.Date(sub("....", 2000, d2))
## Time difference of -1 days

(С другой стороны, мы могли бы выбрать год, который не является високосным, и, поскольку большинство лет не являются високосными, это более вероятноне будьте одного выходного дня для дат с трансграничными датами, однако это будет ценой провала, если одна из дат будет 29 февраля.)

0 голосов
/ 16 декабря 2018

Если нам разрешено быть немного более приблизительными, игнорируя високосные годы, мы можем немного упростить ситуацию, используя %j (день года) в format().

yd_diff <- function(x, y=NULL) {
    x <- as.integer(format(x, "%j"))
    if (is.null(y)) {
        diff(x)
    } else {
        x - as.integer(format(y, "%j"))
    }
}

d1 <- as.Date("2008-12-15")
d2 <- as.Date("2018-12-16")
yd_diff(d1, d2)
# 0

set.seed(1)
rd <- as.Date(sample(1:10000, 5), origin="1970-01-01")
yd_diff(rd)
# -30  180   65 -123

И, что еще проще, мы можем преобразовать дату в целое и взять дни по модулю в году.К счастью, R позволяет использовать по модулю нецелые числа.

(as.integer(d1) %% 365.24) - (as.integer(d2) %% 365.24)
# -0.6

diff(as.integer(rd) %% 365.24)
# -30.72  180.80   64.84 -123.44
0 голосов
/ 16 декабря 2018

Как подсказывает @Omry Atia, мы можем установить для компонента года тот же год, а затем вычислить разницу.

library(lubridate)

get_difference_without_years <- function(x, y) {
    x <- ymd(x)
    year(x) <- 2018
    y <- ymd(y)
    year(y) <- 2018
    x - y
}


get_difference_without_years("2018-12-15", "2018-12-16")
#Time difference of -1 days

get_difference_without_years("2008-12-15", "2018-12-16")
#Time difference of -1 days

Для хранения в базе R

get_difference_without_years <- function(x, y) {
  x <- as.Date(paste0("2018-", format(as.Date(x), "%m-%d")))
  y <- as.Date(paste0("2018-", format(as.Date(y), "%m-%d")))
  x - y
}

get_difference_without_years("2008-12-15", "2018-12-16")
#Time difference of -1 days
get_difference_without_years("2018-12-15", "2018-12-16")
#Time difference of -1 days
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...