Time zone gets lost with lubridate when creating a new datetime component from it

我的未来我决定 提交于 2019-12-24 03:55:34

问题


The following data frame is from a dput. I have used forced_tz on the datatime with no argument. I live in UTC+1 time zone.

library(lubridate)
library(dplyr)

df <- structure(list(value = structure(c(1514967058, 1515148132, 1517472989, 1543844646, 1525085884, 1520584330, 1522838681, 1540379051, 1516707360, 1516705706), 
                                 class = c("POSIXct", "POSIXt"))), 
          .Names = "value", 
          row.names = c(NA, -10L), 
          class = c("tbl_df", "tbl", "data.frame"))


    tz(df$value)
[1] ""

df2 <- df %>% 
  mutate(year=year(value))


    > tz(df2$year)
[1] "UTC"

I have also used tz= "Europe/Paris" but when I extact someting from the datetime (day, month and so on) they loose their time zone and get UTC again. Is it possible to set the time zone once and then get carried over to all every new datetime components that I create?


回答1:


The problem is that year() seems to return a numeric, so it's not anymore a date object.

This is the default method for year():

year.default <- function(x)
    as.POSIXlt(x, tz = tz(x))$year + 1900

So, for example:

y <- as.POSIXlt("2018-01-03 09:10:58 CET", tz = Sys.timezone())$year + 1900
#y
#[1] 2018

Notice that I forced the current tz with Sys.timezone().

But:

class(y)
#[1] "numeric"

So when you call tz(y), since it's numeric it doesn't have a tz attribute, and by default it's given "UTC".

# example:
# tz(123)
# [1] "UTC"

A simple solution is to set yourself the timezone:

attr(y, "tzone") <- Sys.timezone()
y
#[1] 2018
#attr(,"tzone")
#[1] "Europe/Berlin"

So now tz works:

tz(y)
[1] "Europe/Berlin"

I'd advise against this but you could also modify the default method of tz():

my_tz <- function(x) {
  tzone <- attr(x, "tzone")[[1]]
  if (is.null(tzone) && !is.POSIXt(x))
    return(Sys.timezone()) # original was "UTC"
  if (is.character(tzone) && nzchar(tzone))
    return(tzone)
  tzone <- attr(as.POSIXlt(x[1]), "tzone")[[1]]
  if (is.null(tzone))
    return(Sys.timezone()) # original was "UTC"
  tzone
}

my_tz(y)
#[1] "Europe/Berlin"

So now you have a "custom" version of tz() which returns the current timezone whenever the input is not a correct date format.



来源:https://stackoverflow.com/questions/54744899/time-zone-gets-lost-with-lubridate-when-creating-a-new-datetime-component-from-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!