Формат даты и R по сравнению с региональными настройками

Я изо всех сил пытаюсь позволить R придерживаться формата даты / региональных настроек, как указано на моем компьютере с Windows.

У меня есть:

> Sys.getlocale("LC_TIME")
[1] "English_United States.1252"

Но когда я проверяю свою панель управления \ региональные и языковые настройки, у меня есть:

Format: English (United States)
Short date: M/d/yyyy

Похоже, что R полностью игнорирует настройки, относящиеся к дате. Даты в формате R жестко закодированы (?) в фиксированном формате «%Y-%m-%d»:

format.Date(Sys.Date())
[1] "2019-01-25"

Проблема возникает при взаимодействии с данными из внешних программ, которые соответствуют локальным региональным настройкам. Например, даты в формате Microsoft Excel. И сделать код универсальным для разных региональных настроек с разными форматами даты.

Я обнаружил, что это работает в некоторой степени:

sShortDate <- readRegistry("Control Panel\\International", "HCU")$sShortDate
# convert Windows date format strings into R-date-format-strings
CPformat2Rformat <- function(f) {
  f %>%  
  gsub("yyyy", "%Y", .) %>%
  gsub("M",    "%m", .) %>%
  gsub('d',    '%d', .) 
}
sShortDate <- CPformat2Rformat(sShortDate)

# now we have the right format
format.Date(Sys.Date(), sShortDate)
# and the other way around;
strptime("01/25/2019", sShortDate)

Это лучший способ справиться с этим? Или это лучшая функция, которая лучше обрабатывает форматы ShortDate и LongDate?


person Krokkie.za    schedule 25.01.2019    source источник
comment
Я не понимаю, о чем вы спрашиваете. Даты, отформатированные R, жестко закодированы (?) в фиксированном формате %Y-%m-%d Нет ничего жестко закодированного, просто есть (вполне разумное) значение по умолчанию. Вы показываете себе, что можете изменить эту настройку по умолчанию.   -  person Roland    schedule 25.01.2019
comment
Krokkie.za, если один из ответов касается вашего вопроса, примите его; это не только дает небольшое преимущество отвечающему с некоторыми баллами, но также обеспечивает некоторое закрытие для читателей с похожими вопросами. Хотя вы можете принять только один ответ, у вас есть возможность проголосовать за столько, сколько вы считаете полезным. (Если все еще есть проблемы, вам, вероятно, придется отредактировать свой вопрос, указав дополнительные сведения.)   -  person r2evans    schedule 06.02.2019


Ответы (2)


Если я вас правильно понял, вы спрашиваете, почему R не отображает даты для вашей локали. Я согласен, было бы неплохо, если бы вы могли управлять форматом отображаемого объекта Date, сохраняя его как объект Date. Но нет реального способа без предоставления собственного расширения без небольшой работы.

Вот хак: переопределите метод print.Date по умолчанию, хотя он работает только с прямыми переменными в консоли, а не со встроенными, такими как data.frame:

x <- data.frame(dt = Sys.Date(), dttm = Sys.time())
x$dt
# [1] "2019-01-25"
class(x$dt)
# [1] "Date"

print.Date <- function (x, max = NULL, ...) {
    fmt <- getOption("date.format", "%m/%d/%Y")
    if (is.null(max)) 
        max <- getOption("max.print", 9999L)
    if (max < length(x)) {
        print(format(x[seq_len(max)], format=fmt), max = max, ...)
        cat(" [ reached getOption(\"max.print\") -- omitted", 
            length(x) - max, "entries ]\n")
    }
    else if (length(x)) 
        print(format(x, format=fmt), max = max, ...)
    else cat(class(x)[1L], "of length 0\n")
    invisible(x)
}

x
#           dt                dttm
# 1 2019-01-25 2019-01-25 00:22:38
x$dt
# [1] "01/25/2019"
class(x$dt)
# [1] "Date"
options(date.format="%b %d, %Y")
x$dt
# [1] "Jan 25, 2019"

Я определил здесь значение по умолчанию "%m/%d/%Y", но там это соответствует вашим предпочтениям. Более универсальное приложение этой функции может по умолчанию использовать значение R по умолчанию "%Y-%m-%d", и пользователь может изменить его в какой-то момент в зависимости от своих потребностей.

(Я не знаю навскидку, как сделать ссылку на эту функцию для представлений data.frame. Вероятно, это связано с областью действия, где она использует base::print.Date из-за пути поиска пространств имен. Если вы спросите "могу ли я заменить тот", его спрашивали, и обычно ответ был примерно таким: "это могло бы сработать, но..." или "предостережение emtor", и по моему опыту никогда не бывает идеально решенным, особенно при попытке переопределить базовые функции.)

person r2evans    schedule 25.01.2019

Вы можете использовать функцию as.Date() для адаптации к различным форматам даты, например:

as.Date("01/25/2019", format='%m/%d/%Y')
as.Date("Jan-30-2019", format='%b-%d-%Y')
as.Date("25012019", format='%d%m%Y')

все дадут один и тот же общий объект даты.

person Paul    schedule 25.01.2019