Working With Dates
Using lubridate and date.
Dates are tricky because they can be formatted differently, for example 03/01/1999 or 1-3-99, or March 1, 1999. Months and years also have different numbers of days making them hard to add or subtract. For example what is January 31 st plus 1 month?
To start with this will give todays date and time.
d1 <- date()
d1
## [1] "Tue May 26 18:13:37 2015"
The class of this date is just a character.
class(d1)
## [1] "character"
But things get more complicated
d2 <- Sys.Date()
d2
## [1] "2015-05-26"
class(d2)
## [1] "Date"
A date with a date class allows you to reformat the date into a variety of other formats
For example you can take the existing d2 and reformat it like below:
format(d2, "%a %b %d")
## [1] "Tue May 26"
Below is a table of possible date formats. For example adding %Y will add a year to the date. As you can see from the table, upper and lowercase letters are treated differently.
format(d2, "%a %b %d %Y")
## [1] "Tue May 26 2015"
format(d2, "%A %b %d %y")
## [1] "Tuesday May 26 15"
Conversion Spec | Description | Example |
---|---|---|
%a | Abbreviated weekday | Sun, Thu |
%A | Full weekday | Sunday, Thursday |
%b or %h | Abbreviated month | May, Jul |
%B | Full month | May, July |
%d | Day of the month 01-31 | 27, 07 |
%j | Day of the year 001-366 | 148, 188 |
%m | Month 01-12 | 05, 07 |
%U | Week 01-53 with Sunday as first day of the week | 22, 27 |
%w | Weekday 0-6 Sunday is 0 | 0, 4 |
%W | Week 00-53 with Monday as first day of the week | 21, 27 |
%x | Date, locale-specific | |
%y | Year without century 00-99 | 84, 05 |
%Y | Year with century on input: 00 to 68 prefixed by 20 69 to 99 prefixed by 19 | 1984, 2005 |
%C | Century | 19, 20 |
%D | Date formatted %m/%d/%y | 05/27/84, 07/07/05 |
%u | Weekday 1-7 Monday is 1 | 7, 4 |
%n | Newline on output or Arbitrary whitespace on input | |
%t | Tab on output or Arbitrary whitespace on input |
Symbols can also be added between dates.
format(d2, "%A %m/%d/%y")
## [1] "Tuesday 05/26/15"
Creating Dates
You have to tell R that a date is a date and you have to tell it what date elements are in the character vector.
First create a character vector of dates.
x <- c("1jan1960", "2jan1960", "31mar1960", "30jul1960")
class(x)
## [1] "character"
z = as.Date(x, "%d%b%Y")
class(z)
## [1] "Date"
z
## [1] "1960-01-01" "1960-01-02" "1960-03-31" "1960-07-30"
And you can get a time difference from one date to the next.
z[2] - z[1]
## Time difference of 1 days
Julian Conversion
You can get the names of days or months by using the months or weekdays function.
months(d2)
## [1] "May"
weekdays(d2)
## [1] "Tuesday"
And you can get the number of days since the origin, in this case the origin is Jan 1, 1970, which it will tell you.
julian(d2)
## [1] 16581
## attr(,"origin")
## [1] "1970-01-01"
Lubridate
Lubridate makes things quite a bit easier. The function that you use with lubridate tells it what to look for. For example ymd tells it to look for a year then a month and then a day.
library(lubridate)
ymd(20140309)
## [1] "2014-03-09 UTC"
mdy("March 01, 2013")
## [1] "2013-03-01 UTC"
You can also add times.
ymd_hms("09-12-1 3-15-30")
## [1] "2009-12-01 03:15:30 UTC"
lubridate can also weed out unnecessary information and understand rather bizarrely formated dates.
ymd_hms("2009 arbitrary 1 non-decimal 6 chars 12 in between 1 !!! 6")
## [1] "2009-01-06 12:01:06 UTC"
ymd_hms("2009-1, 5 12:1, 5")
## [1] "2009-01-05 12:01:05 UTC"
And you can add timezone information. By default lubridate assumes GMT time.
dmy_hm("03-06-14 4-15", tz="Pacific/Auckland")
## [1] "2014-06-03 04:15:00 NZST"
To get the weekday in lubridate use wday.
wday(d2)
## [1] 3
This gives the day number. To get the day itself add label=TRUE
wday(d2, label=TRUE)
## [1] Tues
## Levels: Sun < Mon < Tues < Wed < Thurs < Fri < Sat
See more here
More about lubridate