Values in a column (class Date) are integers, even though they are forced to be Dates

I have this function code, in a file named utils.R where I create big and large functions to avoide overlaoding my original project.

While everything seems correct and my DataFrame (which has a column named Fecha cierre -closing date-) looks perfect, when I try to print Dates, all belonging to the previosuly mentioned column, the output is this: Ejemplo de fechas reales: 19737 19737 19737 19737 19737 19737 (integer numbers, if you run r as.Date(19737) = "2024-01-15, which is what I want. How can I fix this? I need to have dates, not integers

# utils.R
library(dplyr)
library(lubridate)

prepara_df_ordenado = function(df, fecha_inicio) {
  fecha_inicio = as.Date(fecha_inicio)
  
  req_cols = c("Fecha cierre", "Terna", "Terna_rep", "Tiempo imputado")
  faltan = setdiff(req_cols, names(df))
  if (length(faltan)) stop("Faltan columnas obligatorias: ", paste(faltan, collapse = ", "))
  
  # --- Convertir "Fecha cierre" ---
  if (inherits(df[["Fecha cierre"]], "Date")) {
    cat("'Fecha cierre' ya es Date, se conserva sin cambios.\n")
  } else {
    # cat("\nNo es de tipo fecha. Se trata como numérico.\n")
    # cat(paste0("La fecha de inicio es: ", fecha_inicio, " y es de clase ", class(fecha_inicio)))
    df[["Fecha cierre"]] = as.Date(fecha_inicio) + (as.integer(df[["Fecha cierre"]]) - 1L)
    # cat(paste0("\nLa columna 'Fecha cierre es de clase': ", class(df$`Fecha cierre`)))
  }
  
  stopifnot(inherits(df[["Fecha cierre"]], "Date"))
  
  evolucion_input = NULL
  if ("Evolución imputación" %in% names(df)) {
    evolucion_input = df[["Evolución imputación"]]
    df = dplyr::select(df, -`Evolución imputación`)
  }
  
  if (!is.numeric(df[["Tiempo imputado"]])) {
    df[["Tiempo imputado"]] = suppressWarnings(as.numeric(df[["Tiempo imputado"]]))
  }
  
  df_ordenado = df %>%
    arrange(Terna, `Fecha cierre`, Terna_rep) %>%
    group_by(Terna) %>%
    mutate(
      `Media Acumulada` = cummean(`Tiempo imputado`),
      `Media Previa`    = dplyr::lag(`Media Acumulada`, default = 0)
    ) %>%
    ungroup()
  
  
  list(df_ordenado = df_ordenado, evolucion_input = evolucion_input)
}




iqr_check = function(prev_vals, new_val){
  q1 = as.numeric(quantile(prev_vals, 0.25, na.rm = T))
  q3 = as.numeric(quantile(prev_vals, 0.75, na.rm = T))
  iqr = q3-q1
  lim_inf = q1 - 1.5 * iqr
  lim_sup = q3 + 1.5 * iqr
  isTRUE(new_val >= lim_inf && new_val <= lim_sup)
}

crea_evolucion = function(terna_rep, media_previa, media_acumulada){
  n = substr(terna_rep, nchar(terna_rep), nchar(terna_rep))
  
  ifelse(n == "1" | media_previa == 0,
         0,
         ((media_previa - media_acumulada)/media_previa)*100)
}

calcular_tiempo_objetivo = function(df, ventana = 5){
  df$`Tiempo objetivo`= 0
  df$Productividad = 0
  
  ternas = unique(df$Terna)
  
  for (terna in ternas){
    sub_df = df[df$Terna == terna, , drop = F]
    tiempos = numeric(0)
    
    for (i in seq_len(nrow(sub_df))){
      t_imp = sub_df$`Tiempo imputado`[i]
      tiempos = c(tiempos, t_imp)
      
      ultimos = tail(tiempos, ventana)
      t_obj = mean(ultimos, na.rm = T)
      
      if (length(ultimos) > 1){
        t_obj = t_obj - (sd(ultimos, na.rm = T)/2)
      }
      df[df$Terna == terna, "Tiempo objetivo"][i] = t_obj
      
      if (t_obj > 0){
        prod = (t_obj - t_imp)/t_obj * 100
      } else {
        prod = 0
      }
      df[df$Terna == terna, "Productividad"][i] = prod
    }
  }
  return(df)
}


#' Construye el dataset de imputaciones B
#'
#' Procesa el histórico **día a día** a partir de `df_ordenado`.
#'
#' @param df_ordenado data.frame/tibble con las columnas mínimas
#'   `Fecha cierre`, `Terna`, `Tiempo imputado` y opcionalmente `Key`.
#' @param min_prev integer(1). Mínimo de observaciones previas a considerar
#'   para validar/aceptar una imputación. Por defecto `3`.
#' @param incluir_rechazadas logical(1). Si `TRUE`, incluye explícitamente las
#'   imputaciones rechazadas en el resultado. Por defecto `FALSE`.
#'
#' @return Un `data.frame` con columnas:
#'   `Fecha cierre`, `Key`, `Terna`, `Tiempo imputado`, `Aceptada`,
#'   `Rechazada`, `ultima_imputacion`, `repeticiones`.
#'
#' @details
#' El algoritmo recorre el histórico en orden por `Fecha cierre` y `Terna`,
#' calculando aceptación/rechazo según el criterio definido (p. ej. IQR/medias
#' previas) y añadiendo metadatos como `ultima_imputacion` y `repeticiones`.
#'
#' @examples
#' \dontrun{
#' res = construir_imputaciones_B(df_ordenado, min_prev = 3, incluir_rechazadas = FALSE)
#' head(res)
#' }
#'
#' @export
construir_imputaciones_B_dia_a_dia = function(df_ordenado, min_prev = 4, incluir_rechazadas = FALSE) {
  df = arrange(df_ordenado, .data[["Fecha cierre"]])
  
  # 🔒 Reforzar tipo inicial
  df$`Fecha cierre` = as.Date(df$`Fecha cierre`)
  cat("📅 Tipo inicial de 'Fecha cierre':", class(df$`Fecha cierre`), "\n")
  
  base_cols = c("Key", "Terna", "Operario", "OP", "Fecha cierre","Puesto", "Mes",
                "Tiempo imputado", "Media Previa","Media Acumulada",
                "Fecha cierre", "Terna_rep", "Área")
  
  historial = new.env(parent = emptyenv())
  filas = list()
  fila_idx = 1L
  
  # --- Forzar que cada elemento de 'dias' sea Date ---
  dias_raw <- unique(df$`Fecha cierre`)
  dias_raw <- dias_raw[order(dias_raw)]
  
  # 🔒 Crear vector garantizado de tipo Date
  dias <- as.Date(sapply(dias_raw, function(x) as.Date(x, origin = "1970-01-01")), origin = "1970-01-01")
  
  cat("📆 Ejemplo de días únicos (forzados):", head(dias), "\n")
  

  
  for (dia in dias) {
    # 🔍 Trazar tipo del día
    if (fila_idx == 1L) cat("➡️ Tipo de 'dia' dentro del bucle:", class(dia), "\n")
    
    df_dia = df[df[["Fecha cierre"]] == dia, , drop = FALSE]
    
    # Verificar que sigue siendo Date tras subset
    if (fila_idx == 1L) cat("📅 Tipo tras subset:", class(df_dia$`Fecha cierre`), "\n")
    
    for (i in seq_len(nrow(df_dia))) {
      r = df_dia[i, , drop = FALSE]
      terna = as.character(r[["Terna"]])
      t = as.numeric(r[["Tiempo imputado"]])
      
      if (!exists(terna, envir = historial, inherits = FALSE)) {
        assign(terna, numeric(0), envir = historial)
      }
      
      prev = get(terna, envir = historial)
      suficientes = length(prev) >= min_prev
      
      aceptar = if (!suficientes) TRUE else iqr_check(prev, t)
      
      fila = as.data.frame(r[base_cols], stringsAsFactors = FALSE)
      
      if ("Fecha cierre" %in% names(fila)) {
        fila$`Fecha cierre` = as.Date(fila$`Fecha cierre`, origin = "1970-01-01")
      }
      
      
      if (aceptar) {
        prev = c(prev, t)
        assign(terna, prev, envir = historial)
        filas[[fila_idx]] = fila
        fila_idx = fila_idx + 1L
      } else {
        if (length(filas) > 0) {
          filas = Filter(function(x) !identical(as.character(x$Terna[1]), terna), filas)
        }
        assign(terna, numeric(0), envir = historial)
      }
    }
  }
  
  imputaciones_B = do.call(rbind, filas)
  
  # 🔍 Comprobamos tipo justo después del rbind
  cat("🧩 Clase tras rbind:", class(imputaciones_B$`Fecha cierre`), "\n")
  cat("🧩 Valores ejemplo:", head(imputaciones_B$`Fecha cierre`), "\n")
  
  # ✅ Conversión correcta con origen explícito
  imputaciones_B$`Fecha cierre` = as.Date(imputaciones_B$`Fecha cierre`, origin = "1970-01-01")
  cat("✅ Clase final de 'Fecha cierre' en imputaciones_B:", class(imputaciones_B$`Fecha cierre`), "\n")
  cat("🗓️ Ejemplo de fechas reales:", head(imputaciones_B$`Fecha cierre`), "\n")
  
  
  imputaciones_B$Evolución_imputación_calc = crea_evolucion(
    imputaciones_B$Terna_rep,
    imputaciones_B$`Media Previa`,
    imputaciones_B$`Media Acumulada`
  )
  
  imputaciones_B = calcular_tiempo_objetivo(imputaciones_B, ventana = 5)
  
  list(imputaciones_B = imputaciones_B, historial = as.list(historial))
}




HI, welcome to the forum

Could you supply some sample data?
A handy way to supply data is to use the dput() function. Do dput(mydata) where "mydata" is the name of your dataset. For really large datasets probably dput(head(mydata, 100). Paste it here between

```

```
Thanks.