I suggest rewriting (augmenting) all of your timestamps to begin on the same "Sunday" (or whichever day) using lubridate::floor_date
, and then counting into that week. For instance, some sample data:
set.seed(42)
dat <- data.frame(starttime = as.POSIXct("2000-01-01", tz = "UTC") + 100*86400*runif(10), type = LETTERS[1:10])
dat$endtime <- dat$starttime + 86400*runif(10)
dat$weekstart <- lubridate::floor_date(dat$starttime, "weeks")
dat$start1 <- dat$weekstart[1] + difftime(dat$starttime, dat$weekstart, units = "secs")
dat$end1 <- dat$weekstart[1] + difftime(dat$endtime, dat$weekstart, units = "secs")
head(dat)
# starttime type endtime weekstart start1 end1
# 1 2000-04-01 11:32:04 A 2000-04-01 22:31:13 2000-03-26 2000-04-01 11:32:04 2000-04-01 22:31:13
# 2 2000-04-03 16:58:51 B 2000-04-04 10:14:22 2000-04-02 2000-03-27 16:58:51 2000-03-28 10:14:22
# 3 2000-01-29 14:44:05 C 2000-01-30 13:10:01 2000-01-23 2000-04-01 14:44:05 2000-04-02 13:10:01
# 4 2000-03-24 01:04:27 D 2000-03-24 07:12:16 2000-03-19 2000-03-31 01:04:27 2000-03-31 07:12:16
# 5 2000-03-05 04:11:21 E 2000-03-05 15:17:03 2000-03-05 2000-03-26 04:11:21 2000-03-26 15:17:03
# 6 2000-02-21 21:49:49 F 2000-02-22 20:23:26 2000-02-20 2000-03-27 21:49:49 2000-03-28 20:23:26
range(dat$starttime)
# [1] "2000-01-14 11:11:59 UTC" "2000-04-03 16:58:51 UTC"
range(dat$start1)
# [1] "2000-03-26 04:11:21 UTC" "2000-04-01 14:44:05 UTC"
We'll be using start1
and end1
for plotting. It doesn't matter if we based them all off of dat$weekstart[1]
or min(dat$weekstart)
, since the reference date is never shown, just the day-of-week.
Plot method:
library(ggplot2)
ggplot(dat, aes(y = type)) +
geom_segment(aes(x = start1, xend = end1, yend = type)) +
scale_x_datetime(date_labels = "%a %H:%M")

Some notes about this:
- while
floor_date
supports starting the week on arbitrary days of the week, unless you care, it doesn't matter: the "seconds of the week" is never shown; but if you really want to control it (perhaps for follow-on filtering?), then look into the week_start=
argument.
- since we're keeping
x=
(and xend=
) as proper POSIXt
objects, we can use the native functionality of scale_x_datetime
, including its date_breaks=
(not shown, but could be something like date_breaks="12 hours"
if desired).