title: R / lubridate: Calculate number of overlapping days between two periods
body: <p>I am trying to calculate the number of overlapping days between two time periods. One period is fixed in a start and end date, the other is recorded as start and end dates in a data frame.</p>
  
  <p>Edit: I'm dealing with ads that have publish date (df$start) and an unpublish date (df$end). What I'm trying to find out is how many days they have been online in a specific month (my.start = 2018-01-01, my.end = 2018-08-31).</p>
  
  <pre><code>library(dplyr)
  library(lubridate)
  
  my.start &lt;- ymd("2018-08-01")
  my.end &lt;- ymd("2018-08-31")
  
  df &lt;- data.frame(start = c("2018-07-15", "2018-07-20", "2018-08-15", "2018-08-20", "2018-09-01"), 
                   end   = c("2018-07-20", "2018-08-05", "2018-08-19", "2018-09-15", "2018-09-15"))
  
  # strings to dates
  df &lt;- mutate(df, start = ymd(start), end = ymd(end))
  
  # does not work - calculate overlap in days
  df &lt;- mutate(df, overlap = intersect(interval(my.start, my.end), interval(start, end)))
  </code></pre>
  
  <p>Results should be 0, 5, 4, 12, 0 days:</p>
  
  <pre><code>   my.start |-------------------------------| my.end
  
  |-----| (0)
          |---------| (5)
                              |----| (4)
                                     |------------------| (12)
                                               |---------------| (0)
  </code></pre>
  
  <p>In Excel, I would use </p>
  
  <pre><code>=MAX(MIN(my.end, end) - MAX(my.start, start) + 1, 0)
  </code></pre>
  
  <p>but that doesn't work either:</p>
  
  <pre><code># does not work - calculate via min/max
  df &lt;- mutate(df, overlap = max(min(my.end, end) - max(my.start, start) + 1, 0))
  </code></pre>
  
  <p>Before I try to use the Excel approach using <code>as.numeric()</code> on the dates, I wondered if there is a cleverer way to do this.</p>
  
  <p>EDIT: Actually, the Excel numeric approach doesn't seem two work either (all results are zero):</p>
  
  <pre><code># does not work - calculate via numeric
  
  ms.num &lt;- as.numeric(my.start)
  me.num &lt;- as.numeric(my.end)
  
  df &lt;- df %&gt;% 
    mutate(s.num = as.numeric(start),
           e.num = as.numeric(end),
  
           overlap = max(min(e.num, me.num) - max(s.num, ms.num) + 1, 0))
  </code></pre>
  
  <p>Edit: The approach by @akrun seems to work for ymd dates. However, it doesn't seem to work for ymd_hms times:</p>
  
  <pre><code>library(dplyr)
  library(lubridate)
  library(purrr)
  
  my.start &lt;- ymd("2018-08-01")
  my.end &lt;- ymd("2018-08-31")
  
  df &lt;- data.frame(start = c("2018-07-15 10:00:00", "2018-07-20 10:00:00", "2018-08-15 10:00:00", "2018-08-20 10:00:00", "2018-09-01 10:00:00"), 
                   end   = c("2018-07-20 10:00:00", "2018-08-05 10:00:00", "2018-08-19 10:00:00", "2018-09-15 10:00:00", "2018-09-15 10:00:00"))
  
  # strings to dates
  df &lt;- mutate(df, start = ymd_hms(start), end = ymd_hms(end))
  
  # leads to 0 results
  df %&gt;% mutate(overlap = map2(start, end, ~ sum(seq(.x, .y, by = '1 day') %in% seq(my.start, my.end, by = '1 day'))))
  </code></pre>