4

I'm trying to do some manipulation on the POSIXct vector, but when I pass it to a function, the vector changes into a numeric vector, instead of retaining POSIXct class, even when the function itself only returns the object:

# Sample dates from vector and it's class.
> dates <- as.POSIXct(c("2012-02-01 12:32:00", "2012-10-24 17:25:56", "2008-09-26 17:13:31", "2011-08-23 11:11:17,", "2015-09-19 22:28:33"), tz = "America/Los_Angeles")
> dates
[1] "2012-02-01 12:32:00 PST" "2012-10-24 17:25:56 PDT" "2008-09-26 17:13:31 PDT" "2011-08-23 11:11:17 PDT" "2015-09-19 22:28:33 PDT"
> class(dates)
[1] "POSIXct" "POSIXt" 
# Simple subset is retaining original class.
> qq <- dates[1:5]
> qq
[1] "2012-02-01 12:32:00 PST" "2012-10-24 17:25:56 PDT" "2008-09-26 17:13:31 PDT" "2011-08-23 11:11:17 PDT" "2015-09-19 22:28:33 PDT"
> class(qq)
[1] "POSIXct" "POSIXt" 
# sapply on the same subset using simple "return" function changes class to "numeric" - why? How to retain "POSIXct"?
> qq2 <- sapply(dates[1:5], function(x) x)
> qq2
[1] 1328128320 1351124756 1222474411 1314123077 1442726913
> class(qq2)
[1] "numeric"

Why it happens? How can I retain the POSIXct class of the original vector? I know that POSIXct is numeric under the hood, but I want to retain the original class for readability.

kmo
  • 103
  • 7

1 Answers1

2

We can use lapply instead of sapply as sapply by default has the option simplify = TRUE. So, if the list elements are of the same length, it will simplify it to vector or matrix depending on the length of the list elements and POSIXct is stored as numeric.

lst <- lapply(dates, function(x) x)

If we need to use sapply, then an option would simplify = FALSE

lst <- sapply(dates, function(x) x, simplify=FALSE)

After applying the function, if we need as a vector output,

do.call("c", lst)

Regarding the change of timezone, it is documented in the ?DateTimeClasses

Using c on "POSIXlt" objects converts them to the current time zone, and on "POSIXct" objects drops any "tzone" attributes (even if they are all marked with the same time zone).

So, the possible option would be (as mentioned in the comments by @kmo)

.POSIXct(lst, tz = "America/Los_Angeles")
#[1] "2012-02-01 12:32:00 PST" "2012-10-24 17:25:56 PDT" "2008-09-26 17:13:31 PDT" "2011-08-23 11:11:17 PDT" "2015-09-19 22:28:33 PDT"

Or as @thelatemail mentioned in the comments

.POSIXct(sapply(dates,I), attr(dates,"tzone") )
akrun
  • 874,273
  • 37
  • 540
  • 662
  • @kmo I think you may have to specify the timezone with `tz` – akrun Jul 07 '16 at 10:00
  • Thanks for the answer! I noticed one thing though - after converting to vector the timezone is changed to the local one: `> do.call("c", lapply(dates[1:5], function(x) x)) [1] "2012-02-01 21:32:00 CET" "2012-10-25 02:25:56 CEST" "2008-09-27 02:13:31 CEST" "2011-08-23 20:11:17 CEST" "2015-09-20 07:28:33 CEST"`. Any idea on that one? – kmo Jul 07 '16 at 10:02
  • @kmo In my system, your original dates have `PST ` and `PDT` as time zone. – akrun Jul 07 '16 at 10:09
  • Yes, original ones do have "PST/PDT", but after `do.call("c", lst)` tz is changed to my local timezone, which is "CEST/CET" - I wonder why that happens and how to mitigate this issue. – kmo Jul 07 '16 at 10:18
  • `.POSIXct(lst, tz = "America/Los_Angeles")` brings back the proper timezone, but still don't know why local timezone is used upon vector conversion. – kmo Jul 07 '16 at 10:29
  • @thelatemail THanks for that. Why do you need `dates[0]`? `.POSIXct(c(sapply(dates, I) ), attr(dates,"tzone") )` seems to work for me. – akrun Jul 07 '16 at 11:12
  • 1
    @akrun - I think i've out-tricked myself - I should go to bed! - just `.POSIXct(sapply(dates,I), attr(dates,"tzone") )` will do fine. – thelatemail Jul 07 '16 at 11:14