Dates and times: POSIXct & POSIXlt


To start with we can get R to print out the current date and time using the sys.time function.

Sys.time()
## [1] "2015-05-29 16:16:37 EDT"

If you want you can change the number of decimal seconds that is displayed.

options("digits.secs"=6) 
Sys.time()
## [1] "2015-05-29 16:16:37.262545 EDT"
options("digits.secs"=0) 
datetime <- Sys.time()
datetime
## [1] "2015-05-29 16:16:37 EDT"


We can do the standard julian conversions

weekdays(datetime)
## [1] "Friday"
months(datetime)
## [1] "May"
quarters(datetime)
## [1] "Q2"
julian(datetime)
## Time difference of 16584.84 days

This time has the class “POSIXct” & “POSIXt”.

class(datetime)
## [1] "POSIXct" "POSIXt"

POSIXt is a virtual class which cannot be used directly. “A virtual class ‘POSIXt’ exists from which both of the classes inherit: it is used to allow operations such as subtraction to mix the two classes.”



POSIXct and POSIXlt

POSIXct is the number of seconds since the epoch. In this case the epoch Jan 1st 1970.

POSIXlt is a mixed text and character format like

  • May, 6 1985
  • 1990-9-1
  • 1/20/2012


My understanding is that it is best to use POSIXct as the list structure of a date in POSIXlt can be troublesome and POSIXct takes up quite a bit less memory.


We can create a date using the number of seconds and by supplying an origin.

date1 <- as.POSIXct(1268736919, origin="1970-01-01", tz="GMT")
date2 <- as.POSIXlt(1268736919, origin="1970-01-01", tz="GMT")
date1; date2
## [1] "2010-03-16 10:55:19 GMT"
## [1] "2010-03-16 10:55:19 GMT"


They look identical but we can see the internal difference between POSIXct and POSIXlt using the unclass function

unclass(date1)
## [1] 1268736919
## attr(,"tzone")
## [1] "GMT"
unclass(date2)
## $sec
## [1] 19
## 
## $min
## [1] 55
## 
## $hour
## [1] 10
## 
## $mday
## [1] 16
## 
## $mon
## [1] 2
## 
## $year
## [1] 110
## 
## $wday
## [1] 2
## 
## $yday
## [1] 74
## 
## $isdst
## [1] 0
## 
## attr(,"tzone")
## [1] "GMT"


For POSIXlt objects we can see these elements using the $ symbol

date2$min
## [1] 55
date2$year
## [1] 110

For both class objects we can see the timezone using the attr function.

attr(date1, "tzone")
## [1] "GMT"
attr(date2, "tzone")
## [1] "GMT"



We can also create dates by telling both functions what different numbers mean. If you use the format argument the supplied numbers must be in quotes (character vector). If you don’t use format then the number must be a numeric vector.

date3 <- as.POSIXct("20100316105519", format="%Y%m%d%H%M%S", origin="1970-01-01", tz="GMT")
date4 <- as.POSIXct(20100316105519, origin="1970-01-01", tz="GMT")
date3; date4
## [1] "2010-03-16 10:55:19 GMT"
## [1] "638923-08-30 12:25:19 GMT"
date5 <- as.POSIXlt("20100316105519", format="%Y%m%d%H%M%S", origin="1970-01-01", tz="GMT")
date6 <- as.POSIXlt(20100316105519, origin="1970-01-01", tz="GMT")
date3; date4
## [1] "2010-03-16 10:55:19 GMT"
## [1] "638923-08-30 12:25:19 GMT"
z <- 20100316105519
as.POSIXct(z, format="%Y%m%d%H%M%S", origin="1970-01-01", tz="GMT") # produces an NA because it is expecting a character string.
## [1] NA


Messing around with dates.

We can also create a sequence of dates using seq.POSIXlt.

several_dates <- seq.POSIXt(date2, by=1, length.out = 100)
head(several_dates)
## [1] "2010-03-16 10:55:19 GMT" "2010-03-16 10:55:20 GMT"
## [3] "2010-03-16 10:55:21 GMT" "2010-03-16 10:55:22 GMT"
## [5] "2010-03-16 10:55:23 GMT" "2010-03-16 10:55:24 GMT"

Just a number will increment the seconds, maybe I’d rather increment the days.

The by argument can be specified in several ways.

  • A number, taken to be in seconds.

  • A object of class difftime

  • A character string, containing one of “sec”, “min”, “hour”, “day”, “DSTday”, “week”, “month”, “quarter” or “year”. This can optionally be preceded by a (positive or negative) integer and a space, or followed by “s”.

several_dates <- seq.POSIXt(date2, by="day", length.out = 100)
head(several_dates)
## [1] "2010-03-16 10:55:19 GMT" "2010-03-17 10:55:19 GMT"
## [3] "2010-03-18 10:55:19 GMT" "2010-03-19 10:55:19 GMT"
## [5] "2010-03-20 10:55:19 GMT" "2010-03-21 10:55:19 GMT"

And then cut that season into different breaks

day_weeks<- cut.POSIXt(several_dates, "weeks")
class(day_weeks)
## [1] "factor"
levels(day_weeks)
##  [1] "2010-03-15" "2010-03-22" "2010-03-29" "2010-04-05" "2010-04-12"
##  [6] "2010-04-19" "2010-04-26" "2010-05-03" "2010-05-10" "2010-05-17"
## [11] "2010-05-24" "2010-05-31" "2010-06-07" "2010-06-14" "2010-06-21"

We can get the difference between two times.

datetime - date1 #just subtracting gives days
## Time difference of 1900.39 days

We can also add time to both POSIXct and POSIXlt objects

date1 + 5000
## [1] "2010-03-16 12:18:39 GMT"
date2 + 5000
## [1] "2010-03-16 12:18:39 GMT"