Дата в R — это счётчик дней в костюме
Чтобы превратить строку в настоящую дату, используйте as.Date(); чтобы получить сегодняшний день — Sys.Date(). За обеими стоит простой трюк: класс Date в R — это просто число, счёт дней с 1 января 1970 года, надевшее костюм, из-за которого оно печатается как календарная дата. Костюм можно снять через unclass():
Это 20672 — сырой счёт дней, и именно он заставляет работать всё остальное на этой странице: сравнения, вычитание и последовательности внизу являются обычной целочисленной арифметикой. А костюм делает всё это пригодным к использованию: то же число печатается как дата, форматируется как дата и рисуется на оси дат.
as.Date() спокойно разбирает раскладку ISO "YYYY-MM-DD" без всякой помощи, и это одна из нескольких хороших причин хранить даты в файлах именно так. Одна привычка, которую стоит выработать пораньше: неудачный разбор молча возвращает NA, а не ошибку, — так что всегда бросайте взгляд на результат после разбора чего-то нового.
Строки, которые лишь выглядят как даты, остаются обычными строками: "2026-08-07" < "2026-11-01" случайно сравнивается верно, потому что порядок ISO совпадает с алфавитным, а вот "07/08/2026" сортируется бессмысленно. Сначала преобразуйте, потом сравнивайте.
Разбор других раскладок через format =
Мир не пишет даты в формате ISO. Для всего остального as.Date() принимает аргумент format = — рецепт, описывающий входную строку и собранный из кодов с %.
Все три разбираются в один и тот же день. Рецепт должен точно соответствовать строке, включая разделители: "%d/%m/%Y" не разберёт "07-08-2026". Коды, которыми вы действительно будете пользоваться:
| Код | Значение | Пример |
|---|---|---|
%Y | Год из 4 цифр | 2026 |
%y | Год из 2 цифр | 26 |
%m | Номер месяца | 08 |
%d | День месяца | 07 |
%b | Сокращённое название месяца | Aug |
%B | Полное название месяца | August |
%a | Сокращённый день недели | Fri |
%A | Полный день недели | Friday |
%H | Час (00-23) | 14 |
%M | Минута | 30 |
%S | Секунда | 05 |
Классическая засада — сама строка "07/08/2026": день/месяц/год в большей части мира, месяц/день/год в США, и R не может угадать, что имеет в виду ваш файл. Хуже того, неверная догадка часто «работает» — оба прочтения дают корректные даты, — пока не наступит 13-й день какого-нибудь месяца и не разберётся в NA (тринадцатого месяца не существует). Узнайте соглашение своих данных до того, как писать рецепт.
Форматирование дат для вывода
format() — зеркальное отражение as.Date(): те же коды с %, работающие в обратную сторону — на входе Date, на выходе строка.
Используйте это для заголовков отчётов, подписей и имён файлов — format(Sys.Date(), "%Y-%m-%d") даёт имена, сортирующиеся хронологически. Две детали стоит знать: %d дополняет нулём («August 07»), а %B/%A выдают названия на языке системных настроек — сессия, настроенная на немецкий, напечатает «Freitag» вместо «Friday». Держите форматирование на краях скрипта, для людей; внутри пусть даты остаются датами.
Арифметика дат и последовательности
Поскольку Date — это счётчик дней, арифметика работает так, как хотелось бы. Вычитание двух дат даёт объект difftime:
Три привычки из этого блока. Во-первых, оборачивайте difftime в as.numeric(), прежде чем считать с ним, — difftime несёт атрибут единиц, который может удивить в дальнейших вычислениях. Во-вторых, когда единицы важны, задавайте их через difftime(units = ), а не принимайте то, что выберет R. В-третьих, прибавление обычного числа означает прибавление дней — в базовом R нет + 1 месяц, потому что «один месяц» не является фиксированным числом дней.
Для календарно осведомлённого шага используйте seq(), которая понимает "day", "week", "month", "quarter" и "year":
Месячные последовательности — стандартный инструмент для отчётных периодов и делений оси. Одна причуда: начните месячную последовательность 31-го числа, и R продолжит отсчитывать реальные дни сквозь месяцы, где такого числа нет, поэтому «февральская» запись окажется в начале марта. Привязывайте месячные последовательности к 1-му числу и выводите всё остальное отсюда.
Извлечение частей даты
В базовом R есть два удобных экстрактора и одна общая идиома. weekdays() и months() возвращают названия; для чисел делайте круг через format():
Приём «format(), а затем as.integer()» выглядит окольным, но это стандартная идиома базового R, и она векторизована: передайте ей целый столбец дат — и получите обратно целый столбец годов. Это ровно то, что нужно после импорта датированного набора из CSV-файла: один раз разобрать столбец дат через as.Date(), а затем вывести столбцы года и месяца для группировки.
Когда дней мало: POSIXct и lubridate
У Date нет понятия часов. В момент, когда в ваших данных появляются отметки времени — записи журнала, показания датчиков, «заказ размещён в 14:32», — вам нужен POSIXct, класс даты-времени в R: секунды с 1970 года вместо дней и учёт часового пояса.
Переносится всё: те же коды с % (теперь включая %H, %M, %S) работают при разборе и в format(), вычитание даёт difftime, Sys.time() — это «сейчас». Новое бремя — часовой пояс: при разборе передавайте tz = явно, иначе две сессии в разных поясах прочитают одну и ту же строку как два разных момента. И не поддавайтесь искушению хранить календарные данные как POSIXct «на всякий случай»: день рождения, сохранённый как полночь в каком-то поясе, может напечататься предыдущим днём в другом поясе — по-настоящему мучительный для отслеживания баг. Целые дни — Date. Моменты — POSIXct.
Наконец, пакет lubridate — более дружелюбное лицо, которое большая часть кода tidyverse надевает на всё вышеописанное; его стоит взять на вооружение, когда базовая механика стала понятной:
library(lubridate)
ymd("2026-08-07") # order-based parsing: no format string
mdy("08/07/2026") # ...you just say which order the parts come in
dmy("7 August 2026")
floor_date(Sys.Date(), "month") # snap to the start of the period
ymd(), mdy() и dmy() заменяют форматные рецепты простым указанием порядка частей, а floor_date() решает задачу «сгруппировать эти отметки времени по месяцам» одним вызовом. lubridate едет на тех же классах Date/POSIXct под капотом — это лучший руль, а не другой двигатель.
Что вы уносите с собой
Date— это счёт дней с 1970-01-01, наряженный печататься как дата;unclass()показывает число.as.Date("2026-08-07")разбирает ISO напрямую; всему остальному нужен рецептformat =из кодов с%— а неудачный разбор молча возвращаетNA.format(date, "...")работает в обратную сторону: те же коды, на выходе строки для отображения.- Вычитание даёт difftime — задавайте
units =явно и применяйтеas.numeric()перед вычислениями.+ nприбавляет дни; для месяцев используйтеseq(by = "month"). weekdays(),months()и идиомаas.integer(format(...))вытаскивают части, векторизованно.Date— для целых дней,POSIXct(с явнымtz) — для отметок времени; lubridate делает оба дружелюбнее.
Дальше: что делать, когда R на вас кричит, — как читать сообщения об ошибках и методично их отлаживать.
Часто задаваемые вопросы
Как преобразовать строку в дату в R?
С помощью as.Date(). Если строка в формате ISO, это просто работает: as.Date("2026-08-07"). Любая другая раскладка требует рецепта format =, собранного из кодов с %: as.Date("07/08/2026", format = "%d/%m/%Y"). Неудачный разбор возвращает NA, а не ошибку, поэтому проверяйте результат.
Как получить сегодняшнюю дату в R?
Sys.Date() возвращает сегодняшний день объектом Date; Sys.time() возвращает текущие дату и время как POSIXct. Обе берут данные из часов и настроек часового пояса вашего компьютера.
Как вычислить разницу между двумя датами в R?
Вычтите их: as.Date("2026-08-07") - as.Date("2026-01-01") даёт difftime в 218 дней. Оберните в as.numeric(), чтобы использовать число в вычислениях, или вызовите difftime(d1, d2, units = "weeks"), чтобы выбрать единицы самому, а не оставлять это на усмотрение R.
В чём разница между Date и POSIXct в R?
Date хранит целые дни (внутри — дни с 1970-01-01) и ничего не знает о часах и часовых поясах. POSIXct хранит момент времени (секунды с 1970 года) и учитывает часовой пояс. Используйте Date для календарных данных вроде дней рождения и дедлайнов; используйте POSIXct только когда важно время суток, например для отметок времени и журналов.