R语言Shiny应用中timevis组件的日期时间显示异常问题
修复timevis甘特图日期显示偏移问题
问题
开发的Shiny应用使用timevis包制作甘特图,从dateInput选择的日期,在甘特图和表格中均显示为前一天的22:00:00,存在时区偏移问题。
原因
dateInput默认使用本地时区返回Date类型值,将其转换为UTC时区的POSIXct时,会因本地时区与UTC的时差产生偏移;同时timevis组件默认以UTC时间处理和显示时间数据,进一步放大了这个偏移。
解决方案
通过以下两步修正:
- 给
dateInput指定UTC时区,确保选择的日期直接基于UTC返回; - 转换日期为POSIXct时,明确指定UTC时区并保留当天0点的时间戳,避免时区转换误差。
完整修正代码
library(timevis) library(shiny) ui <- fluidPage( textAreaInput("addText", "Add item:", "service: \n Cost: "), # 指定dateInput使用UTC时区 dateInput("addDate", NULL, Sys.Date(), tz = "UTC"), textAreaInput("group", "Add group:", "Owner:"), actionButton("addBtn", "Add"), timevisOutput("timelineInteractive"), tableOutput("table") ) server <- function(input, output, session) { data_rv <- reactiveValues(data = data.frame(start = as.POSIXct(character(), tz = "UTC"), end = as.POSIXct(character(), tz = "UTC"), content = character(), group = character(), stringsAsFactors = FALSE), userUpdated = FALSE) groups <- reactive({ if(nrow(data_rv$data) == 0) { NULL } else { data.frame(id = unique(data_rv$data$group), content = unique(data_rv$data$group)) } }) observeEvent(input$addBtn, { # 将Date转为带0点的字符串,再转换为UTC时区的POSIXct new_start <- as.POSIXct(paste(input$addDate, "00:00:00"), tz = "UTC") new_item <- data.frame(start = new_start, end = NA, content = gsub("\n", "<br>", input$addText), group = input$group, stringsAsFactors = FALSE) data_rv$data <- rbind(data_rv$data, new_item) data_rv$userUpdated <- FALSE }) output$timelineInteractive <- renderTimevis({ config <- list( editable = TRUE, multiselect = TRUE ) timevis(data = data_rv$data, groups = groups(), options = config) }) observeEvent(input$timelineInteractive_data, { if (!data_rv$userUpdated) { timeline_data <- input$timelineInteractive_data timeline_data$start <- as.POSIXct(timeline_data$start, format = "%Y-%m-%dT%H:%M:%OSZ", tz = "UTC") if ("end" %in% names(timeline_data)) { timeline_data$end <- as.POSIXct(timeline_data$end, format = "%Y-%m-%dT%H:%M:%OSZ", tz = "UTC") } else { timeline_data$end <- NA } timeline_data <- timeline_data[ , c("start", "end", "content", "group")] names(timeline_data) <- c("start", "end", "content", "group") data_rv$userUpdated <- TRUE data_rv$data <- timeline_data } else { data_rv$userUpdated <- FALSE } }) output$table <- renderTable({ data <- input$timelineInteractive_data data }) } shinyApp(ui = ui, server = server)
内容的提问来源于stack exchange,提问作者Haribo
相关产品推荐
相关产品推荐

