Time zone gets lost with lubridate when creating a

2019-07-18 12:20发布

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条回答
\"骚年 ilove
2楼-- · 2019-07-18 13:03

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.

查看更多
登录 后发表回答