【问题标题】:POSIXct objects and time zonesPOSIXct 对象和时区
【发布时间】:2019-11-07 18:03:02
【问题描述】:

我有从 Excel 导入的日期时间数据表和数字格式的日期/时间列(即 43596.22)。我使用以下代码将数字转换为具有 UTC 时区的日期时间格式:

 info_dt1$Date_time<-convertToDateTime(info_dt1$date_time, origin = "1900-01-01",tx="UTC")

我正在使用 data.table 中的 forverlaps 函数按日期和时间将此数据表与另一个数据表合并。当我第一次运行以下代码时:

info_dt3 = foverlaps(info_dt2, info_access3, by.x=c("Date_time", "dummy"), nomatch=NA)[, dummy := NULL]

我收到一条错误消息,指出两个日期时间字段具有不同的时区。其他数据表的时区也指定为 UTC。

我使用 attr 函数将两个数据表的日期时间列设置为 UTC:

   #make sure all date/times have same time zone
attr(info_access2$Start_time, "tzone") <- "UTC"
attr(info_access2$End_time, "tzone") <- "UTC"
attr(info_dt1$Date_time, "tzone") <- "UTC"

当我这样做时,info_dt1 数据表时间向前移动 4 小时,结果合并关闭。我想知道在为两个数据表设置格式和时区以使合并正常工作时我做错了什么。

Some example data and code:

    #first data table reduced example 

        info_dt1<-
        structure(list(date_time = c(NA, 43596.2284722222, 43596.2285069444, 
        43596.2285416667, 43596.2285763889, 43596.2286111111, 43596.2286458333, 
        43596.2286805556, 43596.2287152778, 43596.22875), Temp = c(NA, 
        22.75, 22.66, 22.57, 22.49, 22.37, 22.28, 22.16, 22.08, 21.99
        ), Depth = c(NA, 0.19, 0.27, 0.7, 0.27, 0.27, 0.27, 0.19, 0.19, 
        0.19), Angle = c(NA, -3, -4, -3, -1, 1, -1, -2, 1, -6)), .Names = c("date_time", 
        "Temp", "Depth", "Angle"), row.names = c(NA, 10L), class = "data.frame")

        #convert date time to POSIXct
         info_dt1$Date_time<-convertToDateTime(info_dt1$date_time, origin = "1900-01-01",tx="UTC")

        #second example data set
        info_access2<-
        structure(list(Tow = 201905001:201905010, Start_time = structure(c(1557554271, 
        1557564948, 1557569853, 1557573081, 1557577149, 1557582317, 1557586050, 
        1557588636, 1557590697, 1557593679), class = c("POSIXct", "POSIXt"
        ), tzone = "UTC"), End_time = structure(c(1557555117, 1557565710, 
        1557570765, 1557573846, 1557577974, 1557583210, 1557586797, 1557589428, 
        1557591441, 1557594511), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
            time_interval = structure(c(846, 762, 912, 765, 825, 893, 
            747, 792, 744, 832), start = structure(c(1557554271, 1557564948, 
            1557569853, 1557573081, 1557577149, 1557582317, 1557586050, 
            1557588636, 1557590697, 1557593679), class = c("POSIXct", 
            "POSIXt"), tzone = "UTC"), tzone = "UTC", class = structure("Interval", package = "lubridate"))), .Names = c("Tow", 
        "Start_time", "End_time", "time_interval"), row.names = c(NA, 
        10L), class = "data.frame")

    library(data.table)

    #make info_dt2 and info_access2 data.tables
    info_access3<-as.data.table(info_access2)
    info_dt2<-as.data.table(info_dt1)

    #remove NA from info_dt2
    info_dt2<-info_dt2[complete.cases(info_dt2),]

    #set dummy column for info_dt2
    info_dt2[, dummy := Date_time]

    #define setkey for info_access2
    setkey(info_access3, Start_time, End_time)

    #if I run the code like this I get the error message about different time zones

    #use foverlaps to merge info_access3 and info_dt2
    info_dt3 = foverlaps(info_dt2, info_access3, by.x=c("Date_time", "dummy"), nomatch=NA)[, dummy := NULL]

    #if I run this chunk of code the times in info_dt1 are moved forward 4 hours
     #make sure all date/times have same time zone
        attr(info_access2$Start_time, "tzone") <- "UTC"
        attr(info_access2$End_time, "tzone") <- "UTC"
        attr(info_dt1$Date_time, "tzone") <- "UTC"

#make info_dt2 and info_access2 data.tables
    info_access3<-as.data.table(info_access2)
    info_dt2<-as.data.table(info_dt1)

    #remove NA from info_dt2
        info_dt2<-info_dt2[complete.cases(info_dt2),]


    #but the foverlaps to merge info_access2 and info_dt2 doesn't give an error message
        info_dt3 = foverlaps(info_dt2, info_access3, by.x=c("Date_time", "dummy"), nomatch=NA)[, dummy := NULL]

【问题讨论】:

    标签: r datetime data.table


    【解决方案1】:

    您可以使用lubridate::force_tz() 更改读取时具有不准确时区的时间戳:

    lubridate::force_tz(Sys.time(), "UTC")
    #[1] "2019-06-25 14:04:32 UTC"
    

    这将更改底层时间戳双精度,而仅更改属性不会。

    【讨论】:

    • 不幸的是,这似乎使问题变得更糟。 foverlaps 合并之间的任何日期/时间都不匹配。为什么我为每个数据表指定 UTC 时时区会有所不同?
    • 在更彻底地阅读你的代码后,我想我可能已经发现了问题——在convertToDateTime() 你有tx = "UTC"(这不是as.POSIXct() 的论据所以它被默默地吞下了...) 而不是 tz = "UTC"。解决此问题后,我的解决方案应该可以工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 2013-03-22
    相关资源
    最近更新 更多