Menu

Fechas en R: as.Date, format() y aritmética de fechas

La clase Date de R es un conteo de días disfrazado. Cómo parsear cadenas con as.Date, formatear fechas para la salida, restarlas, construir secuencias y cuándo necesitas POSIXct en su lugar.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Una fecha en R es un conteo de días disfrazado

Para convertir una cadena en una fecha de verdad, usa as.Date(); para obtener hoy, usa Sys.Date(). Detrás de ambas hay un truco sencillo: la clase Date de R es solo un número — el conteo de días desde el 1 de enero de 1970 — con un disfraz encima que hace que se imprima como una fecha de calendario. Puedes quitarle el disfraz con unclass():

Ese 20672 es el conteo de días en crudo, y es lo que hace funcionar todo lo demás en esta página: las comparaciones, la resta y las secuencias son solo aritmética de enteros por debajo. El disfraz es lo que la hace usable: el mismo número se imprime como fecha, se formatea como fecha y se grafica en un eje de fechas.

as.Date() parsea encantada la disposición ISO "YYYY-MM-DD" sin ayuda, que es una de varias buenas razones para almacenar las fechas así en tus archivos. Un hábito para construir pronto: un parseo fallido devuelve NA en silencio — no un error — así que echa siempre un vistazo al resultado tras parsear algo nuevo.

Las cadenas que meramente parecen fechas siguen siendo solo cadenas: "2026-08-07" < "2026-11-01" da la casualidad de que se compara correctamente porque el orden ISO coincide con el alfabético, pero "07/08/2026" se ordena como un disparate. Convierte primero, compara después.

Parsear otras disposiciones con format =

El mundo no escribe fechas ISO. Para todo lo demás, as.Date() acepta un argumento format =: una receta que describe la cadena entrante, construida con códigos %.

Las tres se parsean al mismo día. La receta debe coincidir exactamente con la cadena, separadores incluidos: "%d/%m/%Y" no parseará "07-08-2026". Los códigos que usarás de verdad:

CódigoSignificadoEjemplo
%YAño de 4 dígitos2026
%yAño de 2 dígitos26
%mNúmero de mes08
%dDía del mes07
%bNombre de mes abreviadoAug
%BNombre de mes completoAugust
%aDía de la semana abreviadoFri
%ADía de la semana completoFriday
%HHora (00-23)14
%MMinuto30
%SSegundo05

La emboscada clásica es "07/08/2026" en sí: día/mes/año en la mayor parte del mundo, mes/día/año en EE. UU., y R no puede adivinar cuál quiere decir tu archivo. Peor: una suposición errónea a menudo "funciona" — ambas lecturas son fechas válidas — hasta que llega el día 13 de algún mes y se parsea a NA (no existe el mes 13). Conoce la convención de tus datos antes de escribir la receta.

Formatear fechas para la salida

format() es la imagen especular de as.Date(): los mismos códigos %, corriendo en dirección contraria — Date dentro, cadena fuera.

Usa esto para títulos de informes, etiquetas y nombres de archivo — format(Sys.Date(), "%Y-%m-%d") produce nombres que se ordenan cronológicamente. Dos detalles que conviene saber: %d rellena con ceros ("August 07"), y %B/%A producen nombres en el idioma configurado en tu sistema — una sesión configurada en alemán imprime "Freitag" en lugar de "Friday". Mantén el formateo en los bordes de tu script, para humanos; internamente, deja las fechas como Dates.

Aritmética de fechas y secuencias

Como una Date es un conteo de días, la aritmética funciona como cabría esperar. Restar dos fechas da un objeto difftime:

Tres hábitos para llevarte de ese bloque. Primero, envuelve un difftime en as.numeric() antes de hacer cálculos con él — difftime lleva un atributo de unidades que puede sorprender a cálculos posteriores. Segundo, cuando las unidades importan, decláralas con difftime(units = ) en lugar de aceptar lo que R escoja. Tercero, sumar un número a secas significa sumar días — no existe + 1 mes en R base, porque "un mes" no es un número fijo de días.

Para avanzar con conciencia de calendario, usa seq(), que entiende "day", "week", "month", "quarter" y "year":

Las secuencias mensuales son la herramienta estándar para períodos de informes y cortes de eje. Una peculiaridad: empieza una secuencia mensual el día 31 y R sigue contando días reales a través de los meses que no lo tienen, así que la entrada de "febrero" cae a principios de marzo. Ancla las secuencias mensuales en el día 1 y deriva cualquier otra cosa a partir de ahí.

Extraer partes de una fecha

R base tiene dos extractores de conveniencia y un idioma general. weekdays() y months() devuelven nombres; para números, haz el viaje de ida y vuelta por format():

El movimiento format()-y-luego-as.integer() parece dar un rodeo, pero es el idioma estándar de R base, y está vectorizado: dale una columna entera de fechas y recibes una columna entera de años de vuelta. Eso es exactamente lo que quieres tras importar un conjunto de datos con fechas desde un archivo CSV: parsea la columna de fechas una vez con as.Date() y luego deriva columnas de año y mes para agrupar.

Cuando los días no bastan: POSIXct, y lubridate

Date no tiene concepto de horas. En cuanto tus datos tienen timestamps — entradas de log, lecturas de sensores, "pedido realizado a las 14:32" — necesitas POSIXct, la clase de fecha-hora de R: segundos desde 1970 en lugar de días, y consciente de la zona horaria.

Todo se traslada: los mismos códigos % (ahora incluyendo %H, %M, %S) funcionan para el parseo y para format(), la resta da difftimes, Sys.time() es "ahora". La nueva carga es la zona horaria — pasa tz = explícitamente al parsear, porque de lo contrario dos sesiones en zonas distintas leerán la misma cadena como dos instantes diferentes. Y resiste la tentación de almacenar datos de calendario como POSIXct "por si acaso": un cumpleaños almacenado como medianoche-en-alguna-zona puede imprimirse como el día anterior en otra zona, un bug genuinamente miserable de rastrear. Días enteros: Date. Instantes: POSIXct.

Por último, el paquete lubridate es la cara más amable que la mayoría del código tidyverse le pone a todo lo anterior — vale la pena adoptarlo una vez que la mecánica base tenga sentido:

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() y dmy() reemplazan las recetas de formato con una simple declaración del orden de las partes, y floor_date() resuelve "agrupa estos timestamps por mes" en una sola llamada. lubridate cabalga sobre las mismas clases Date/POSIXct por debajo — un volante mejor, no un motor distinto.

Lo que te llevas

  • Una Date es un conteo de días desde 1970-01-01 disfrazado para imprimirse como fecha; unclass() muestra el número.
  • as.Date("2026-08-07") parsea ISO directamente; cualquier otra cosa necesita una receta format = de códigos % — y un parseo fallido devuelve NA, en silencio.
  • format(fecha, "...") es el inverso: los mismos códigos, produciendo cadenas para mostrar.
  • La resta da un difftime — establece units = explícitamente, as.numeric() antes de hacer cálculos. + n suma días; para meses, usa seq(by = "month").
  • weekdays(), months() y el idioma as.integer(format(...)) extraen partes, vectorizados.
  • Date para días enteros, POSIXct (con un tz explícito) para timestamps; lubridate hace ambos más amables.

A continuación: qué hacer cuando R te grita — leer mensajes de error y depurarlos con método.

Preguntas frecuentes

¿Cómo se convierte una cadena a fecha en R?

Con as.Date(). Si la cadena está en formato ISO, funciona sin más: as.Date("2026-08-07"). Cualquier otra disposición necesita una receta format = construida con códigos %: as.Date("07/08/2026", format = "%d/%m/%Y"). Un parseo fallido devuelve NA en lugar de un error, así que revisa el resultado.

¿Cómo se obtiene la fecha de hoy en R?

Sys.Date() devuelve hoy como un objeto Date; Sys.time() devuelve la fecha-hora actual como POSIXct. Ambas salen del reloj y la configuración de zona horaria de tu ordenador.

¿Cómo se calcula la diferencia entre dos fechas en R?

Réstalas: as.Date("2026-08-07") - as.Date("2026-01-01") da un difftime de 218 días. Envuélvelo en as.numeric() para usar el número en cálculos, o llama a difftime(d1, d2, units = "weeks") para elegir tú las unidades en lugar de dejar que R decida.

¿Cuál es la diferencia entre Date y POSIXct en R?

Date almacena días enteros (internamente: días desde 1970-01-01) y no sabe nada de horas ni de zonas horarias. POSIXct almacena un instante en el tiempo (segundos desde 1970) y es consciente de la zona horaria. Usa Date para datos de calendario como cumpleaños y fechas límite; usa POSIXct solo cuando importa la hora del día, como en timestamps y logs.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR