【问题标题】:time zone printed in list, but attribute blank时区打印在列表中,但属性为空白
【发布时间】:2018-02-20 15:39:56
【问题描述】:

我使用库 RODBC 从数据库中提取信息。

library(RODBC)
stats <- function(user, pswd){
  qry <- " select mydatetime from bar"
  cn <- odbcConnect("A", uid=user, pwd= pswd)
  rst <- sqlQuery(cn, qry, stringsAsFactors = F)
  odbcClose(cn)
  rm(list = c("cn", "qry"))
  rst
}
my_list <- stats("a", "b")

我对输出感到困惑。这是一个 POSIXct 日期时间。当我my_list$mydatetime列表时,它是这样呈现的:

  [1] "2018-01-19 14:54:23 CET" "2018-01-19 14:53:22 CET" "2018-01-19 14:52:53 CET" "2018-01-19 14:51:50 CET"
  [5] "2018-01-12 11:32:44 CET" "2018-01-12 11:32:02 CET" "2018-01-19 06:53:35 CET" "2018-01-19 06:52:06 CET"
  [9] "2018-01-16 08:50:46 CET" "2018-01-16 08:49:59 CET" "2018-01-16 08:51:47 CET" "2018-01-15 05:31:53 CET"

注意CET,这是正确的时区。当我运行attr(my_list$mydatetime,"tzone") 时,我得到""

我的问题不是如何添加时区,而是为什么在打印列表时显示时区-这很令人困惑,因为我假设它被视为 CET 日期时间,事实上,它似乎是一个没有时区的日期时间?

【问题讨论】:

  • 看来你的疑惑是对的。当我从数据库中读取同样的事情时,似乎时区设置为系统时区。类似的讨论在这里:stackoverflow.com/questions/37688509/…。但是当我设置一个新的POSIXct 对象library(lubridate);testTime1&lt;-ymd_hm("2018-01-01 00:00") 时区设置为UTC

标签: r datetime


【解决方案1】:

查看print.POSIXct 的源代码,我们看到以下内容:

print.POSIXct <- function (x, tz = "", usetz = TRUE, ...) 
{
  max.print <- getOption("max.print", 9999L)
  FORM <- if (missing(tz)) 
    function(z) format(x, usetz = usetz)
  else function(z) format(x, tz = tz, usetz = usetz)
  if (max.print < length(x)) {
    print(FORM(x[seq_len(max.print)]), ...)
    cat(" [ reached getOption(\"max.print\") -- omitted", 
      length(x) - max.print, "entries ]\n")
  }
  else print(if (length(x)) 
    FORM(x)
  else paste(class(x)[1L], "of length 0"), ...)
  invisible(x)
}

这里的关键点是,无论是否填充了“tzone”属性,x 都使用format.POSIXct 进行格式化。深入研究另一层,我们可以看到format.POSIXct 看起来像这样:

format.POSIXct <- function (x, format = "", tz = "", usetz = FALSE, ...) 
{
  if (!inherits(x, "POSIXct")) 
    stop("wrong class")
  if (missing(tz) && !is.null(tzone <- attr(x, "tzone"))) 
    tz <- tzone
  structure(format.POSIXlt(as.POSIXlt(x, tz), format, usetz, 
    ...), names = names(x))
}

同样,如果“tzone”属性存在,则通过它传播。无论是否存在,POSIXct 对象在打印之前都会被强制转换为POSIXlt 对象。现在我们掉下了悬崖,因为as.POSIXlt 有一个直接对 R 解释器的内部调用,所以我们不能轻松地调试源代码。

但是,我们可以阅读 POSIXlt 类 (?POSIXlt) 的文档,我们发现:

“POSIXlt”对象通常有一个属性“tzone”,一个长度为 3 的字符向量,给出来自 TZ 环境变量的时区名称以及基本时区和备用(夏令时)时区的名称.有时这可能只是长度为 1,给出时区名称。

因此,POSIXlt 对象确实有一个默认时区,取自系统范围的 TZ 环境变量。此外,我们阅读下一段:

“POSIXct”对象也可能有一个属性“tzone”,一个长度为1的字符向量。如果设置为非空值,它将确定对象如何转换为“POSIXlt”类,特别是如何打印。这通常是可取的,但如果您想在特定时区指定对象但要在当前时区打印,您可能需要删除“tzone”属性(例如,通过 c(x))。

所以POSIXct 类中的“tzone”属性是告诉该类在转换为POSIXlt(例如打印)时使用哪个时区,如果您想要它使用使用本地时区的默认行为

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 1970-01-01
    • 2020-07-28
    • 2019-11-27
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    相关资源
    最近更新 更多