@@ -44,12 +44,64 @@ has_star <- function(x) {
4444 stringr :: str_detect(x , " [*x?]" )
4545}
4646
47+ # ' Helper for coercion to obtain decent messages when coercion does not work
48+ # ' @noRd
49+ check_coerce <- function (x , cofun , atomicclass ) {
50+ result <- suppressWarnings(do.call(cofun , list (x )))
51+ failures = is.na(result ) & ! is.na(x )
52+ if (any(failures )) {
53+ wrong <- paste0(" '" , x [failures ], " '" , collapse = " , " )
54+ rlang :: warn(c(glue :: glue(" Expected {atomicclass} values but obtained {wrong}" ), i = " Replacing with NA" ), use_cli_format = TRUE )
55+ }
56+ return (result )
57+ }
58+
59+ # ' Helper function for coercion to date
60+ # ' Dates are evil
61+ # ' @noRd
62+ asdate <- function (x ) {
63+ # Excel origin date
64+ excel_origin <- " 1899-12-30"
65+
66+ if (is.integer(x ) || is.numeric(x )) {
67+ return (as.Date(as.integer(x ), origin = excel_origin ))
68+ }
69+
70+ if (inherits(x , " POSIXct" ) || inherits(x , " Date" )) {
71+ return (as.Date(x ))
72+ }
73+
74+ if (is.character(x )) {
75+ trynumeric <- suppressMessages(as.numeric(x ))
76+ if (! anyNA(trynumeric )) {
77+ return (as.Date(as.integer(trynumeric ), origin = excel_origin ))
78+ } else {
79+ # Try to parse as Date, catch errors
80+ tryCatch(
81+ as.Date(x ),
82+ error = function (e ) {
83+ rlang :: warn(c(
84+ glue :: glue(" Can't convert character '{x}' to Date: {e$message}" ),
85+ " i" = " Returning NA"
86+ ), use_cli_format = TRUE )
87+ as.Date(NA )
88+ }
89+ )
90+ }
91+ } else {
92+ rlang :: warn(c(
93+ glue :: glue(" Can't convert object of class {class(x)} to Date" ),
94+ " i" = " Returning NA"
95+ ), use_cli_format = TRUE )
96+ as.Date(NA )
97+ }
98+ }
4799
48100# ' Coerce a character vector based on atomicclass
49101# ' @param x A character vector
50102# ' @param atomicclass A character string indicating the atomic class
51103# ' @description
52- # ' About date conversion: read_excel() reads dates as the correct POSIXct object
104+ # ' About date conversion: read_excel() reads dates as the correct POSIXct object
53105# ' when the excel field is formatted as a date. However, if the field is formatted
54106# ' as a number, it will be read as a numeric value. In this case, the conversion to
55107# ' a date object must be performed using the as.Date() function. The origin
@@ -70,13 +122,9 @@ has_star <- function(x) {
70122coerce <- function (x , atomicclass ) {
71123 switch (atomicclass ,
72124 " character" = as.character(x ),
73- " numeric" = as.numeric(x ),
74- " integer" = as.integer(x ),
75- " logical" = as.logical(x ),
76- " date" = if (inherits(x , " POSIXct" ) || inherits(x , " Date" )) {
77- as.Date(x )
78- } else {
79- as.Date(as.integer(x ), origin = " 1899-12-30" )
80- },
125+ " numeric" = check_coerce(x , " as.numeric" , " numeric" ),
126+ " integer" = check_coerce(x , " as.integer" , " integer" ),
127+ " logical" = check_coerce(x , " as.logical" , " logical" ),
128+ " date" = check_coerce(x , " asdate" , " date" ),
81129 )
82130}
0 commit comments