我正在尝试从PostgreSQL数据库中提取数据,并且时间戳字段的结果不一致。我不确定我是否正确处理POSIXct结果。否则,我想我在RPostgreSQL包中发现了一个错误。以下是复制问题的方法:
假设postgres数据库中有一个表有一个字段(在PostgreSQL中运行):
CREATE DATABASE mydb;
CREATE TABLE test_table
(
"DateTime" timestamp without time zone NOT NULL,
CONSTRAINT "pk_test_table" PRIMARY KEY ("DateTime")
)
WITH (
OIDS=FALSE
);
ALTER TABLE test_table
OWNER TO postgres;
让我们说有几百条记录。我将在R中填充它们。这是代码:
library(RPostgreSQL)
# Let's feed the table with some sequence of date/time values
date_values <- as.chron(seq(10000, 10500, 1/24))
format.chron <- function(z) {
sprintf("%04.0f-%02.0f-%02.0f %02.0f:%02.0f:00",
as.numeric(as.character(years(z))),
months(z),
as.numeric(as.character(days(z))),
as.numeric(as.character(hours(z))),
as.numeric(as.character(minutes(z))))
}
.generateInsertQuery <- function(date_values, field_name, table_name) {
insert_val <- paste(paste0("(", sQuote(format(date_values)), ")"), collapse=',')
qry <- paste("INSERT INTO", dQuote(table_name), paste0("(", dQuote(field_name), ")"), "VALUES", insert_val)
qry
}
drv <- dbDriver('PostgreSQL')
con <- dbConnect(drv, user='postgres', dbname='mydb')
qry <- .generateInsertQuery(date_values, "DateTime", "test_table")
dbSendQuery(con, qry)
如果我尝试获取值,时间组件将从结果数据中删除
res <- dbGetQuery(con, "SELECT * FROM test_table")
res[1:20,1]
然而,结果的类是POSIXct
class(res[,1])
如果一次获取一条记录的结果,则小时:分钟等于00:00的值会使时间分量松散:
rs <- dbSendQuery(con, "SELECT \"DateTime\" FROM test_table")
res_list <- list()
for(i in 1:100) res_list[i] <- fetch(rs,1)
res_list
作为一种解决方法,我一次获取结果1条记录,修复并将它们聚合到data.frame中。但这非常耗时,特别是对于大型数据集。有关为什么会发生这种情况以及如何处理这个问题的任何想法?
提前致谢!
答案 0 :(得分:4)
dbWriteTable
将创建类型为timestamp with timezone
的数据库字段,无论时间区域是什么,都会使用tz +00
。我认为更精确的是创建timestamp without timezone
。
dbReadTable
和dbWriteTable
的最佳解决方案是使用Sys.setenv(TZ = "UTC")
。
在我看来,它的依赖性太深,因为R会话中的许多其他进程可能需要适当的时区设置。
更具体而不是深度依赖是定义自己的dbReadTable
和dbWriteTable
,它将DBI
版本包含在适当的posixct类型的预处理/后处理中。但如果您正在开发兼容DBI的代码/包(不仅仅是与postgres相关),那么它仍然不是一个选项。
将RPostgreSQL迁移到github以便于贡献会很棒。
答案 1 :(得分:3)
首先,RPostgreSQL项目有一个邮件列表;我建议你发帖。
PostgreSQL有两种日期时间类型:有和没有时区。我记得,R只映射后者。我确实为此编写了一些早期的回归测试(参见包源代码),但最近还没有参与该项目。但我记得POSIXct来回映射到PostgreSQL日期时间类型就好了。