我认为您已经指出了 RPostgreSQL 中的一个错误:它似乎没有从 R 获取 POSIXct 对象的时区。通过将时间戳格式化为与 UTC 有偏移的字符,可以将时区信息正确传递给 PostgreSQL(参见本答案底部的示例;添加于 2018-09-21)。但首先,这是一个明显错误的说明:
修改您的代码:
library(RPostgreSQL)
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, port = "5432", user= "postgres",
dbname = "test")
# timestamps in three different time zones
dt1 <- as.POSIXct("2016-01-01 10:20:10", tz="US/Eastern")
dt2 <- as.POSIXct("2016-01-01 10:20:10", tz="UTC")
dt3 <- as.POSIXct("2016-01-01 10:20:10", tz="Asia/Tokyo")
df <- data.frame(dt1=dt1, dt2=dt2, dt3=dt3)
q <- "
CREATE TABLE test_table
(
dt1 timestamp with time zone,
dt2 timestamp with time zone,
dt3 timestamp with time zone,
PRIMARY KEY (dt1)
)"
dbSendQuery(con, q)
dbWriteTable(con, "test_table", df, overwrite=FALSE, append=T, row.names=0)
df2 <- dbReadTable(con, "test_table")
请注意,所有三个时间戳都是相同的时区,未正确处理
df2$dt1
“美国东部时间 2016 年 1 月 1 日 10:20:10”
df2$dt2
“美国东部时间 2016 年 1 月 1 日 10:20:10”
df2$dt3
“美国东部时间 2016 年 1 月 1 日 10:20:10”
在 postgres 中也是如此 - 如在 pgadmin 中所见
这表明 postgres 没有从 R 获取时区
请注意,如果我们手动更改 test_table 中的一个时区(例如,pgadmin 中的第一条记录)
例如,
并获取
df2 <- dbReadTable(con, "test_table")
然后正确处理时区
df2$dt1
“2016-01-01 05:20:10 EST”
df2$dt2
“美国东部时间 2016 年 1 月 1 日 10:20:10”
df2$dt3
“美国东部时间 2016 年 1 月 1 日 10:20:10”
因此,这表明 RPostgreSQL没有正确地将时区信息传递给 postgres,但 RPostgreSQL 正确地从 postgres 获取时区信息。
回答原始问题
要使用 RPostgreSQL 将带有时区的时间戳从 R 传递到 Postgres,只需将其格式化为具有 UTC 偏移量的字符串(例如,“2016-01-01 10:20:10-0500”;例如,使用format
然后传递它到 Postgres,同上。
例如:
#convert POSIXct to character with offset from UTC
df$dt1 <- format(df$dt1, format = "%Y-%m-%d %H:%M:%OS%z")
df$dt2 <- format(df$dt2, format = "%Y-%m-%d %H:%M:%OS%z")
df$dt3 <- format(df$dt3, format = "%Y-%m-%d %H:%M:%OS%z")
##> df
## dt1 dt2 dt3
##1 2016-01-01 10:20:10-0500 2016-01-01 10:20:10+0000 2016-01-01 10:20:10+0900
q <- "
CREATE TABLE test_table2
(
dt1 timestamp with time zone,
dt2 timestamp with time zone,
dt3 timestamp with time zone,
PRIMARY KEY (dt1)
)"
dbSendQuery(con, q)
dbWriteTable(con, "test_table2", df, overwrite=FALSE, append=T, row.names=0)
df3 <- dbReadTable(con, "test_table2")
#Note that times are now correct (in local time zone)
##> df3$dt1
##[1] "2016-01-01 10:20:10 EST"
##> df3$dt2
##[1] "2016-01-01 05:20:10 EST"
##> df3$dt3
##[1] "2015-12-31 20:20:10 EST"