Study day

Date subtraction for –DY

SAS: date minus date, INTCK('day', ...), CDISC --DY

CDISC --DY has no day 0. The reference start date is day 1. Dates before the reference stay negative and are not shifted. Raw subtraction is not --DY on or after the reference date.

Quick reference

library(dplyr)

# CDISC --DY has no day 0. The reference date is day 1, not day 0.
if_else(date < rfstdt, date - rfstdt, date - rfstdt + 1)

# same rule, no branch:
as.integer(date - rfstdt) + as.integer(date >= rfstdt)
R SAS
date - rfstdt date minus date (raw, includes day 0)
if_else(date < rfstdt, date - rfstdt, date - rfstdt + 1) --DY (no day 0)
as.integer(date - rfstdt) + as.integer(date >= rfstdt) the same --DY rule, compact

Three traps: raw subtraction is not --DY. On the reference date the raw diff is 0; --DY is 1. Dates before the reference stay negative and do not shift. Missing either date must stay missing, not become day 0.

Worked examples below.

Raw diff versus --DY

Five lab dates around one reference start: two before, the reference date, two after.

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
lb <- data.frame(
  USUBJID = c(
    "STD-001-0001", "STD-001-0001", "STD-001-0001",
    "STD-001-0001", "STD-001-0001"
  ),
  LBDT   = as.Date(c(
    "2025-06-01", "2025-06-02", "2025-06-03",
    "2025-06-04", "2025-06-05"
  )),
  RFSTDT = as.Date("2025-06-03")
)

lb |>
  mutate(
    RAW  = as.integer(LBDT - RFSTDT),
    LBDY = if_else(
      LBDT < RFSTDT,
      as.integer(LBDT - RFSTDT),
      as.integer(LBDT - RFSTDT) + 1L
    )
  )
       USUBJID       LBDT     RFSTDT RAW LBDY
1 STD-001-0001 2025-06-01 2025-06-03  -2   -2
2 STD-001-0001 2025-06-02 2025-06-03  -1   -1
3 STD-001-0001 2025-06-03 2025-06-03   0    1
4 STD-001-0001 2025-06-04 2025-06-03   1    2
5 STD-001-0001 2025-06-05 2025-06-03   2    3
LBDT vs RFSTDT raw LBDY
two days before -2 -2
one day before -1 -1
on the reference date 0 1
one day after 1 2
two days after 2 3

The day before and the day after the reference are not symmetric. SAS date arithmetic returns the raw column. --DY is the LBDY column.

ImportantThere is no day 0

date - rfstdt on the reference date is 0. --DY on that date is 1. Every date on or after the reference is shifted by +1. Dates before the reference remain a negative offset. The raw diff labels the first treatment day as 0 and offsets every later day by one.

Compact form

Add 1 when date >= rfstdt, otherwise add 0:

lb |>
  mutate(
    LBDY = as.integer(LBDT - RFSTDT) + as.integer(LBDT >= RFSTDT)
  )
       USUBJID       LBDT     RFSTDT LBDY
1 STD-001-0001 2025-06-01 2025-06-03   -2
2 STD-001-0001 2025-06-02 2025-06-03   -1
3 STD-001-0001 2025-06-03 2025-06-03    1
4 STD-001-0001 2025-06-04 2025-06-03    2
5 STD-001-0001 2025-06-05 2025-06-03    3

as.integer(TRUE) is 1. as.integer(FALSE) is 0. Same values as if_else(). date - rfstdt is a difftime; as.integer() converts it before the +1.

A subject table

Two subjects. STD-001-0002 starts on 2025-06-10 and has one lab on that day. Missing LBDT remains missing.

lb2 <- data.frame(
  USUBJID = c(
    "STD-001-0001", "STD-001-0001", "STD-001-0001",
    "STD-001-0002", "STD-001-0002"
  ),
  LBDT = as.Date(c(
    "2025-06-02", "2025-06-03", "2025-06-04",
    "2025-06-10", NA
  )),
  RFSTDT = as.Date(c(
    "2025-06-03", "2025-06-03", "2025-06-03",
    "2025-06-10", "2025-06-10"
  ))
)

lb2 |>
  mutate(
    LBDY = as.integer(LBDT - RFSTDT) + as.integer(LBDT >= RFSTDT)
  )
       USUBJID       LBDT     RFSTDT LBDY
1 STD-001-0001 2025-06-02 2025-06-03   -1
2 STD-001-0001 2025-06-03 2025-06-03    1
3 STD-001-0001 2025-06-04 2025-06-03    2
4 STD-001-0002 2025-06-10 2025-06-10    1
5 STD-001-0002       <NA> 2025-06-10   NA

STD-001-0001 study days: -1, 1, 2. STD-001-0002: 1, then NA. Do not replace missing dates with 0. CDISC leaves --DY missing when either date is missing.

INTCK('day', rfstdt, date) in SAS is the raw interval, not --DY. Apply the same +1 on and after the reference date.