Clases disponibles para objetos fecha/hora

R dispone en su paquete base de dos clases específicamente diseñadas para tratar con datos de tipo fecha/hora: Date (solo para fechas) y POSIXt (además de la fecha incluye hora y huso horario); esta última clase contiene dos subclases, POSIXct y POSIXlt que se diferencian simplemente en la forma en que almacenan internamente la fecha y la hora. El paquete lubridate dispone de diversas funciones que facilitas la extracción de componentes de un objeto fecha/hora de clase POSIXct

El término POSIX engloba a una colección de estándares de acceso a funciones del sistema operativo. Es un acrónimo de Portable Operating System Interface. La X procede del sistema operativo UNIX, si bien estos estándares son también válidos para otros sistemas. En R las clases POSIXct y POSIXlt hacen uso de estos estándares para acceder al almacenamiento de fechas y horas.

Ambas clases POSIX almacenan una fecha y hora como el número de segundos transcurridos desde el 1 de enero de 1970. La clase POSIXct almacena internamente esta cifra como un número entero, mientras que la clase POSIXlt la descompone en una lista con elementos para los segundos, minutos, horas, día, mes y año. La clase Date, por su parte, almacena las fechas como el número de días transcurridos también desde el 1 de enero de 1870.



Fechas: clase Date

La clase Date almacena sus valores internamente como el número de días transcurridos desde el 1 de enero de 1970; para las fechas anteriores el número de días se cuenta en sentido negativo.

Conversión de variables tipo carácter en fechas de la clase Date

Para crear una fecha en R el modo más sencillo es utilizar la función as.Date(). Esta función recibe como argumento un dato de fecha en modo carácter y la convierte a la clase Date. En esta clase, el estándar de fecha que se utiliza (en el que se leen y muestran las fechas si no se indica otra cosa) es “año-mes-día” (yyyy-mm-dd). Veamos un ejemplo:

navidad=as.Date("2013-12-25")
navidad
## [1] "2013-12-25"
class(navidad)
## [1] "Date"

Si introducimos la fecha en otro formato (por ejemplo “dia/mes/año”), hemos de indicarlo al usar as.Date para que R pueda interpretar la fecha correctamente:

navidad=as.Date("25/12/2013",format="%d/%m/%Y")
navidad
## [1] "2013-12-25"
navidad=as.Date("25-dic-13",format="%d-%b-%y")
navidad
## [1] "2013-12-25"
navidad=as.Date("25 Diciembre 2013",format="%d %B %Y")
navidad
## [1] "2013-12-25"



Esta conversión opera también sobre vectores (siempre que estén codificados del mismo modo):

dias=c("1/10/2005","2/2/2006","3/4/2006","8/11/2014")
dias
## [1] "1/10/2005" "2/2/2006"  "3/4/2006"  "8/11/2014"
as.Date(dias,format="%d/%m/%Y")
## [1] "2005-10-01" "2006-02-02" "2006-04-03" "2014-11-08"




Formatos de fecha

Para formatear una fecha se pueden utilizar los siguientes símbolos:

Símbolo Significado
%d día (numérico, de 0 a 31)
%a día de la semana abreviado a tres letras
%A día de la semana (nombre completo)
   
%m mes (numérico de 0 a 12)
%b mes (nombre abreviado a tres letras)
%B mes (nombre completo)
   
%y año (con dos dígitos)
%Y año (con cuatro dígitos)




Fecha actual

La función Sys.Date() lee la fecha actual del reloj de nuestro ordenador y la codifica como oun objeto de la clase Date:

Sys.Date()
## [1] "2019-02-07"




Conversión de variables tipo fecha a variables tipo carácter

Las funciones as.character() o format() pueden utilizarse indistintamente para convertir variables de clase Date en variables de clase character. Por defecto, ambas funciones devuelven la fecha (en modo carácter) con el formato estándar de R (año-mes-dia):

fNav1=as.character(navidad)
fNav1
## [1] "2013-12-25"
fNav2=format(navidad)
fNav2
## [1] "2013-12-25"
class(fNav1)
## [1] "character"
class(fNav2)
## [1] "character"



Si se desea presentar la fecha como carácter en formatos distintos del estándar podemos utilizar:

as.character(navidad, format="%d %b. %Y")
## [1] "25 dic. 2013"
as.character(navidad, format="%A, %d de %B de %Y")
## [1] "miércoles, 25 de diciembre de 2013"
as.character(navidad, format="%d/%m/%y")
## [1] "25/12/13"



De modo equivalente, utilizando format():

format(navidad,"%d %b. %Y")
## [1] "25 dic. 2013"
format(navidad,"%A, %d de %B de %Y")
## [1] "miércoles, 25 de diciembre de 2013"
format(navidad, "%d/%m/%y")
## [1] "25/12/13"

Incluso podemos presentar sólo partes de la fecha, como pueden ser el día o el mes:

format(navidad,"%A")
## [1] "miércoles"
format(navidad,"%B")
## [1] "diciembre"


Estas funciones operan también sobre vectores:

fechas=as.Date(c("1/10/2005","2/2/2006","3/4/2006","8/11/2014"))
format(fechas,"%B")
## [1] "octubre"   "febrero"   "abril"     "noviembre"


¡¡ATENCIÓN!!: Tanto as.character() como format() están diseñadas para actuar también sobre caracteres. Por tanto, instrucciones como las siguientes:

as.character("2013-12-25")
## [1] "2013-12-25"
format("2013-12-25")
## [1] "2013-12-25"

no tienen ningún efecto ya que “2013-12-25” es ya una variable de clase carácter y por tanto convertirla en carácter es dejarla como está. Tratar de especificar un formato concreto tampoco produce ningún resultado, ya que “2013-12-25” no es una variable de clase fecha y por tanto no se puede formatear como tal.

as.character("2013-12-25", format="%d/%m/%Y")
## [1] "2013-12-25"


Los siguientes comandos incluso dan un error por tratar de aplicarlos a un carácter:

format("2013-12-25","%d/%m/%Y")
## Error in format.default("2013-12-25", "%d/%m/%Y"): argumento 'trim' inválido
format("2013-12-25","%A")
## Error in format.default("2013-12-25", "%A"): argumento 'trim' inválido


Solo funcionan si primero convertimos el carácter a fecha:

format(as.Date("2013-12-25"),"%A")
## [1] "miércoles"



  1. ¿Qué día de la semana era el 20 de julio de 1969? (llegada del hombre a la luna)
  2. ¿Qué día de la semana llegó Colón a América? (12 de octubre de 1492)
  3. ¿En qué día de la semana naciste?




Codificación interna de objetos de clase Date.

La función unclass() nos muestra la representación interna de un objeto en R. Para un objeto de la clase Date como hemos dicho antes, dicha representación consiste en el número de días transcurridos desde el 1/1/1970:

unclass(as.Date("1970-1-1"))
## [1] 0
unclass(as.Date("1970-1-10"))
## [1] 9
unclass(as.Date("1969-12-20"))
## [1] -12



Operaciones con variables de clase Date

Diferencia de fechas

Si se restan dos variables de clase Date, R nos devuelve la diferencia en días:

dia1=as.Date("25/12/2012",format="%d/%m/%Y")
dia2=as.Date("20/1/2013",format="%d/%m/%Y")
dia3=as.Date("25/12/2013",format="%d/%m/%Y")
dia2-dia1
## Time difference of 26 days
dia3-dia1
## Time difference of 365 days

Podemos calcular la diferencia en semanas, en horas, en minutos, …:

difftime(dia3, dia1, units = "weeks")
## Time difference of 52.1429 weeks
difftime(dia3, dia1, units = "days")
## Time difference of 365 days
difftime(dia3, dia1, units = "hours")
## Time difference of 8760 hours
difftime(dia3, dia1, units = "mins")
## Time difference of 525600 mins
difftime(dia3, dia1, units = "secs")
## Time difference of 31536000 secs



Suma (o diferencia) de un entero y una fecha

Al sumar (restar) un número entero a una fecha, la fecha se adelanta (retrasa) en ese número de días:

dia3-10
## [1] "2013-12-15"
dia3+42
## [1] "2014-02-05"



diff: Diferencias entre fechas sucesivas en un vector

La función diff() calcula la diferencia, en días, entre los términos sucesivos de un vector de fechas (declaradas con clase date):

dias=as.Date(c("1/10/2005","2/2/2006","3/4/2006","6/8/2006"),format="%d/%m/%Y")
diff(dias)
## Time differences in days
## [1] 124  60 125

Sucesiones de fechas

La función seq() puede aplicarse también a objetos de clase date; es posible especificar secuencias de longitud determinada entre dos fechas, o especificar el tiempo entre fechas de la secuencia en días, semanas o meses:

seq(dia1,dia3,length=10)
##  [1] "2012-12-25" "2013-02-03" "2013-03-16" "2013-04-25" "2013-06-05"
##  [6] "2013-07-15" "2013-08-25" "2013-10-04" "2013-11-14" "2013-12-25"
seq(dia1,dia3,by=15)
##  [1] "2012-12-25" "2013-01-09" "2013-01-24" "2013-02-08" "2013-02-23"
##  [6] "2013-03-10" "2013-03-25" "2013-04-09" "2013-04-24" "2013-05-09"
## [11] "2013-05-24" "2013-06-08" "2013-06-23" "2013-07-08" "2013-07-23"
## [16] "2013-08-07" "2013-08-22" "2013-09-06" "2013-09-21" "2013-10-06"
## [21] "2013-10-21" "2013-11-05" "2013-11-20" "2013-12-05" "2013-12-20"
seq(dia1,dia3,by="week") 
##  [1] "2012-12-25" "2013-01-01" "2013-01-08" "2013-01-15" "2013-01-22"
##  [6] "2013-01-29" "2013-02-05" "2013-02-12" "2013-02-19" "2013-02-26"
## [11] "2013-03-05" "2013-03-12" "2013-03-19" "2013-03-26" "2013-04-02"
## [16] "2013-04-09" "2013-04-16" "2013-04-23" "2013-04-30" "2013-05-07"
## [21] "2013-05-14" "2013-05-21" "2013-05-28" "2013-06-04" "2013-06-11"
## [26] "2013-06-18" "2013-06-25" "2013-07-02" "2013-07-09" "2013-07-16"
## [31] "2013-07-23" "2013-07-30" "2013-08-06" "2013-08-13" "2013-08-20"
## [36] "2013-08-27" "2013-09-03" "2013-09-10" "2013-09-17" "2013-09-24"
## [41] "2013-10-01" "2013-10-08" "2013-10-15" "2013-10-22" "2013-10-29"
## [46] "2013-11-05" "2013-11-12" "2013-11-19" "2013-11-26" "2013-12-03"
## [51] "2013-12-10" "2013-12-17" "2013-12-24"
seq(dia1,dia3,by="month")
##  [1] "2012-12-25" "2013-01-25" "2013-02-25" "2013-03-25" "2013-04-25"
##  [6] "2013-05-25" "2013-06-25" "2013-07-25" "2013-08-25" "2013-09-25"
## [11] "2013-10-25" "2013-11-25" "2013-12-25"
seq(dia1,dia3,by="2 weeks")
##  [1] "2012-12-25" "2013-01-08" "2013-01-22" "2013-02-05" "2013-02-19"
##  [6] "2013-03-05" "2013-03-19" "2013-04-02" "2013-04-16" "2013-04-30"
## [11] "2013-05-14" "2013-05-28" "2013-06-11" "2013-06-25" "2013-07-09"
## [16] "2013-07-23" "2013-08-06" "2013-08-20" "2013-09-03" "2013-09-17"
## [21] "2013-10-01" "2013-10-15" "2013-10-29" "2013-11-12" "2013-11-26"
## [26] "2013-12-10" "2013-12-24"
seq(dia1,dia3,by="3 months")
## [1] "2012-12-25" "2013-03-25" "2013-06-25" "2013-09-25" "2013-12-25"





Fecha y hora en la clase POSIXct

Esta clase permite manejar la hora además de la fecha. El almacenamiento interno de una fecha en formato POSIXct es el número de segundos transcurridos desde el 1 de enero de 1970. Para fechas anteriores se usan números negativos.

Conversión de variables tipo carácter en Fecha/Hora (clase POSIXct)

Esta conversión ser realiza mediante la función as.POSIXct; se puede especificar sólo una fecha, o una fecha y una hora:

fh1=as.POSIXct("01/10/1983",format="%d/%m/%Y")
class(fh1)
## [1] "POSIXct" "POSIXt"
fh2=as.POSIXct("01/10/1983 22:10:00",format="%d/%m/%Y %H:%M:%S")
class(fh2)
## [1] "POSIXct" "POSIXt"

Nótese que en la conversión, R incluye también la zona temporal que figura en la configuración de nuestro ordenador. Las zonas temporales son los nombres que reciben los husos horarios (ver http://es.wikipedia.org/wiki/Huso_horario, http://en.wikipedia.org/wiki/List_of_tz_database_time_zones o http://en.wikipedia.org/wiki/Tz_database). R muestra los nombres de todos los husos horarios mediante la función OlsonNames(). En concreto, Canarias se encuentra en la zona WET (Western European Time), que pasa a denominarse WEST (Western European Summer Time) cuando se activa el horario de verano.

Si quisiéramos especificar una fecha y hora correspondiente a otro huso horario deberíamos especificarlo mediante la opción tz; por ejemplo, si la hora que queremos introducir corresponde a la ciudad de Los Angeles en California EEUU, que está incluída en el huso horario PDT (Pacific Daylight Time), usaríamos:

as.POSIXct("01/10/1983 22:10:00",format="%d/%m/%Y %H:%M:%S", tz="PDT")
## [1] "1983-10-01 22:10:00 PDT"



Utilizando la función unclass() podemos ver la representación interna de los objetos de esta clase (número de segundos desde el 1-1-1970):

unclass(fh1)
## [1] 433814400
## attr(,"tzone")
## [1] ""



La función Sys.time() muestra la hora actual del sistema en clase POSIXct:

Sys.time()
## [1] "2019-02-07 17:18:50 WET"

Operaciones con Fechas/Horas de clase POSIXct

Dado que esta clase almacena la fecha/hora en segundos, las operaciones con objetos de esta clase se realizan en segundos:

fh1
## [1] "1983-10-01 WET"
fh1+20
## [1] "1983-10-01 00:00:20 WET"
fh1-30
## [1] "1983-09-30 23:59:30 WET"
fh2-fh1
## Time difference of 22.1667 hours



Si se utiliza difftime() se pueden especificar las unidades:

difftime(fh2,fh1)
## Time difference of 22.1667 hours
difftime(fh2,fh1,units="days")
## Time difference of 0.923611 days
difftime(fh2,fh1,units="weeks")
## Time difference of 0.131944 weeks



Al calcular la diferencia entre dos horas, se tiene en cuenta el efecto del cambio de horario en el horario de verano respecto al de invierno:

as.POSIXct("2013-03-10 08:32:07") - as.POSIXct("2013-03-09 23:55:26")
## Time difference of 8.61139 hours





Fecha y hora en la clase POSIXlt

Como hemos mencionado más arriba, la clase POSIXlt se diferencia de POSIXct en que la primera almacena sus valores en forma de lista. Esta lista contiene el año, mes, dia, hora, minutos y segundos en componentes separadas, por lo que su extracción resulta sencilla. Otros elementos de la lista son el día de la semana, el día del año, la variable isdst (que vale 0 en horario de verano y 1 en horario de invierno), el uso horario y la variable gmtoff que cuenta el número de segundos de desfase respecto a GMT, Greenwich Meridian Time u hora del meridiano de Greenwich). Así, por ejemplo, podemos definir:

fh3=as.POSIXlt("2013-03-10 08:32:07") 
class(fh3)
## [1] "POSIXlt" "POSIXt"
unclass(fh3)
## $sec
## [1] 7
## 
## $min
## [1] 32
## 
## $hour
## [1] 8
## 
## $mday
## [1] 10
## 
## $mon
## [1] 2
## 
## $year
## [1] 113
## 
## $wday
## [1] 0
## 
## $yday
## [1] 68
## 
## $isdst
## [1] 0
## 
## $zone
## [1] "WET"
## 
## $gmtoff
## [1] NA



Podemos acceder a los componentes de esta fecha mediante:

fh3$sec
## [1] 7
fh3$min
## [1] 32
fh3$hour
## [1] 8
fh3$mon
## [1] 2
fh3$year
## [1] 113



Aunque el almacenamiento interno sea en forma de lista, al igual que el caso de la clase POSIXct las operaciones con objetos de la clase POSIXlt se realizan en segundos:

fh3+20
## [1] "2013-03-10 08:32:27 WET"
fh3-180
## [1] "2013-03-10 08:29:07 WET"





El paquete lubridate

Este paquete añade funciones que facilitan la manipulación de fechas expresadas en la clase POSIXct. La conversión de caracteres a dicha clase puede hacerse utilizando funciones definidas por combinaciones de las letras d, m, y (day, month, year) y h, m, s (_horas, minutos y segundos). Así dmy_hms espera día-mes-año-horas-minutos-segundos en ese orden; si usamos ymd_h espera año-mes-dia-hora en es orden, … Los siguientes ejemplos muestran el uso de estas funciones:

library(lubridate)
## 
## Attaching package: 'lubridate'
## The following object is masked from 'package:base':
## 
##     date
fh4=ymd_hms("2013-03-10 08:32:07") 
class(fh4)
## [1] "POSIXct" "POSIXt"
fh5=dmy_hm("1/10/1963 08:32") 
class(fh5)
## [1] "POSIXct" "POSIXt"
fh5
## [1] "1963-10-01 08:32:00 UTC"
fh6=dmy("1 10 1963") 
class(fh6)
## [1] "Date"
fh6
## [1] "1963-10-01"



Podemos fácilmente extraer el mes, día, año, semana, etc de una fecha mediante las funciones disponibles en este paquete:

month(fh5)
## [1] 10
week(fh4)
## [1] 10
year(fh6)
## [1] 1963
wday(fh5) # Dia de la semana
## [1] 3
hour(fh4)
## [1] 8
tz(fh4)
## [1] "UTC"



Otras funciones útiles para la manipulación de fechas en lubridate:

round_date(fh4,"hour")
## [1] "2013-03-10 09:00:00 UTC"
round_date(fh4,"day")
## [1] "2013-03-10 UTC"
round_date(fh4,"month")
## [1] "2013-03-01 UTC"
now()     # Hora actual
## [1] "2019-02-07 17:18:51 WET"
today()   # Fecha actual
## [1] "2019-02-07"








© 2016 Angelo Santana, Carmen N. Hernández, Departamento de Matemáticas   ULPGC