Dint: A tooblox for year-quarter and year-month dates

Stefan Fleck

2018-08-10

library(dint)

dint helps you with working with year-quarter and year-month dates. It is implemented in base R and comes with zero external dependencies. Even if you don’t need to work with such special dates directly, dint can still help you format (for example) plot axis.

Creating


# date_* Objects can be created using explicit constructors...
date_yq(2015, 1)
#> 2015-Q1
date_ym(c(2015, 2016), c(1, 2))
#> 2015-M01 2016-M02


# ...or through coercion of dates or integers
as_date_yq(Sys.Date())
#> 2018-Q3
as_date_yq(20141)   # the last digit is interpreted as quarter
#> 2014-Q1
as_date_ym(201412)  # the last two digits are interpreted as month
#> 2014-M12

Coercion


# You can coerce dates to any date_xx object with as_date_**
d <- as.Date("2018-05-12")
as_date_yq(d)
#> 2018-Q2
as_date_ym(d)
#> 2018-M05
as_date_y(d)
#> 2018


# Conversely, you can convert date_xx objects back to the various R Date formats
q <- date_yq(2015, 1)
as.Date(q)
#> [1] "2015-01-01"
as.POSIXlt(q)
#> [1] "2015-01-01 UTC"


# as.POSIXct creates datetimes in UTC/GMT, so the result might not always be as
# expected, depending on your local timezone.
as.POSIXct(q)
#> [1] "2015-01-01 01:00:00 CET"
as.POSIXct(q, tz = "GMT")
#> [1] "2015-01-01 01:00:00 CET"
print(as.POSIXct(q), tz = "GMT")
#> [1] "2015-01-01 GMT"
print(as.POSIXct(q), tz = "CET")
#> [1] "2015-01-01 01:00:00 CET"

Arithmetics

# Quarters
q <- date_yq(2014, 4)
q
#> 2014-Q4
q + 1
#> 2015-Q1
seq(q -2, q + 2)
#> 2014-Q2 2014-Q3 2014-Q4 2015-Q1 2015-Q2


# Months
m <- date_ym(2014, 12)
m
#> 2014-M12
m + 1
#> 2015-M01
seq(m -2, m + 2)
#> 2014-M10 2014-M11 2014-M12 2015-M01 2015-M02

Accessing elements

q <- date_yq(2014, 4)
get_year(q)
#> [1] 2014
get_quarter(q)
#> [1] 4
get_month(q) # defaults to first month of quarter
#> [1] 10


m <- date_ym(2014, 12)
get_year(m)
#> [1] 2014
get_quarter(m)
#> [1] 4
get_month(m)
#> [1] 12

If you use lubridate, you can just use the slighly less verbose lubridate accessors

stopifnot(requireNamespace("lubridate"))

lubridate::year(q)
#> [1] 2014
lubridate::quarter(q)
#> [1] 4
lubridate::month(q)
#> [1] 10

You can also get the first and last days of calendar periods with dint

q <- date_yq(2015, 1)
first_day_of_quarter(q)  # the same as as.Date(q), but more explicit
#> [1] "2015-01-01"
last_day_of_quarter(q)  # the same as as.Date(q), but more explicit
#> [1] "2015-03-31"


# These functions work with normal dates
d <- as.Date("2018-05-12")
first_day_of_quarter(d)
#> [1] "2018-04-01"
last_day_of_quarter(d)
#> [1] "2018-06-30"
first_day_of_month(d)
#> [1] "2018-05-01"
last_day_of_month(d)
#> [1] "2018-05-31"
first_day_of_year(d)
#> [1] "2018-01-01"
last_day_of_year(d)
#> [1] "2018-12-31"


# Alternativeley you can also use these:
first_day_yq(2012, 2)
#> [1] "2012-04-01"
last_day_ym(2012, 2)
#> [1] "2012-02-29"
last_day_y(2012)
#> [1] "2012-12-31"

Formatting

Formating date_yq objects is easy. Currently, three different formatting presets are defined for dint dates.

q <- date_yq(2014, 4)
format(q, "iso")  # default
#> [1] "2014-Q4"
format(q, "short")
#> [1] "2014.4"
format(q, "shorter")
#> [1] "14.4"


m <- date_ym(2014, 12)
format(m, "iso")  # default
#> [1] "2014-M12"
format(m, "short")
#> [1] "2014.12"
format(m, "shorter")
#> [1] "14.12"

For convenience, dint provides direct formatting functions for dates that are useful for labelling ggplot axis.

library(ggplot2)

x <- data.frame(
  time  = seq(as.Date("2016-01-01"), as.Date("2016-08-08"), by = "day")
)

x$value <- rnorm(nrow(x))

p <- ggplot(
  x,
  aes(
    x = time, 
    y = value)
  ) + geom_point()


print(p)

print(p + scale_x_date(labels = format_date_yq_iso))

print(p + scale_x_date(labels = format_date_ym_short))