haven icon indicating copy to clipboard operation
haven copied to clipboard

Add support for `e8601dn` and `b8601dn` SAS formats

Open gowerc opened this issue 4 months ago • 2 comments

SAS has the formats b8601dn & e8601dn which are used to display just the date component of a datetime variable. Currently haven appears to just read these in as numeric rather than casting to POSIXct/POSIXt. Interestingly similar formats such as b8601dt & e8601dt already appear to be supported.

libname outlib "./data";
data outlib.test_datetimes;
    format 
        my_dt datetime23.4
        dt_8601n b8601dn.
        dt_8601t b8601dt.
        dt_8601en e8601dn.
        dt_8601et e8601dt.
    ;
    input
        my_dt :datetime20. 
    ;
    array dts{*} dt_8601n dt_8601t dt_8601en dt_8601et;
    do i = 1 to dim(dts);
        dts{i} = my_dt;
    end;
    drop i;
    datalines;
01JAN2024:12:34:56.8765
30JUL1756:00:45:00.1234
03MAR2092:01:55:10.0987
25DEC2024:23:05:20.6789
.
;
run;
dat <- haven::read_sas("./data/test_datetimes.sas7bdat")
dat[, c("dt_8601n", "dt_8601t", "dt_8601en", "dt_8601et")]
# A tibble: 5 × 4
      dt_8601n dt_8601t               dt_8601en dt_8601et          
         <dbl> <dttm>                     <dbl> <dttm>             
1  2019731697. 2024-01-01 12:34:56  2019731697. 2024-01-01 12:34:56
2 -6419344500. 1756-07-30 00:45:00 -6419344500. 1756-07-30 00:45:00
3  4170966910. 2092-03-03 01:55:10  4170966910. 2092-03-03 01:55:10
4  2050787121. 2024-12-25 23:05:20  2050787121. 2024-12-25 23:05:20
5          NA  NA                           NA  NA  

gowerc avatar Aug 04 '25 12:08 gowerc

Hey @gowerc,

No worries, this is a super easy update to make! Although these formats only display the date in SAS they do contain the time component as well, so assuming these would be best to treat as datetime on the way in (but open to any thoughts on preferences).

We only translate a limited number of date/time/datetime formats, are there any others that you think would be useful to add at the same time?

https://github.com/tidyverse/haven/blob/190f7a9ababae53ea4bfb85e4183c21881644c29/src/haven_types.cpp#L53-L72

gorcha avatar Nov 24 '25 05:11 gorcha

Hey @gorcha ,

Thanks for looking at this.

The full list of sas datetime formats can be found here: https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/leforinforref/n0p2fmevfgj470n17h4k9f27qjag.htm#n0oinu87dfdce5n1qk15z6ih8w3n

That being said its pretty excessive... Scanning a bunch of code at my company I think what you have already covers 99.9% of what is used in practice (DATETIME being by far the most common).

Although these formats only display the date in SAS they do contain the time component as well, so assuming these would be best to treat as datetime on the way in

I would agree, I think you are risk data loss / truncation if you convert down to dates so would advise against that. Likewise despite what is displayed in SAS they are still datetimes in SAS (e.g. VAR + 1 adds 1 second not one day) so makes sense to me to retain them as datetimes.

gowerc avatar Nov 24 '25 10:11 gowerc