Why does append convert timestamps in R? - r

I want to join a list of time zones into one long vector. Append seems to convert the time zones into the system time zone? Why?
> times = list(as.POSIXct("2015-01-01", tz = 'UTC', origin = "1970-01-01"),
+ as.POSIXct("2015-01-02", tz = 'UTC', origin = "1970-01-01"))
> times
[[1]]
[1] "2015-01-01 UTC"
[[2]]
[1] "2015-01-02 UTC"
> do.call(append, times)
[1] "2014-12-31 19:00:00 EST" "2015-01-01 19:00:00 EST"
I can't use unlist as it strips the list of the POSIXct class. What is the alternative?

Related

date from number of days in R?

I have col of number of days since 1970-01-01 00:00:00 UTC that I want to convert to date and time UTC.
I tried this:
z <- Sys.time()
j=floor(unclass(z)/86400) # the number of days since 1970-01-01 (UTC)
as.POSIXct(j, origin = "1970-01-01")
[1] "1970-01-01 05:53:22 CET"
But it is not correct. any idea?
You have to pass to the function as.POSIXct the number of seconds, try this code
j<-17148.5625000000
as.POSIXct(j*24*60*60, origin = "1970-01-01", tz="UTC")
[1] "2016-12-13 13:30:00 UTC"
If you want only the day in output
as.Date(as.POSIXct(j*24*60*60, origin = "1970-01-01", tz="UTC"))
[1] "2016-12-13"

Converting Navy sunset/sunrise data into time

I have downloaded the 2015-2017 sunset/sunrise data from the Navy and I am trying to format it into dates and time to further use with other data I have. This is how my data set looks in R.
I have managed to convert the date into the right R data format. Yet, I still can't convert my rise/set column data from a number/integer format to a time data (as hh:mm).
Based on one internet source, I wrote the following codes:
Sun2015$Srise<- format(strptime(Sun2015$Rise, format="%H:%M"))
However this gives NA in my data
OR
Sun2015$Srise<-str_pad(Sun2015$Rise, 4, pad="0")
Sun2015$Srise<-hour(hm(Sun2015$Srise))
Yet, I received the following error:
Warning message: In .parse_hms(..., order = "HM", quiet = quiet) :
Some strings failed to parse.
Is there a better way to convert the columns into the right time format so that I can merge the date and time columns into date-time columns for sunset and sunrise?
Thank you in advance for your help.
You can convert your military time to 2400 time strings using sprint("%04d", data) and go from there. For example, with the first 5 lines of your data:
# Sample of your data
Day <- c("1/1/2015", "1/2/2015", "1/3/2015", "1/4/2015", "1/5/2015")
Rise <- c(652,652,652,653,653)
Set <- c(1755,1756,1756,1757,1757)
sun2015 <- data.frame(Day, Rise, Set)
# Convert to 2400 style strings with leading zeroes where necessary
sun2015$Rise <- sprintf("%04d", sun2015$Rise)
sun2015$Set <- sprintf("%04d", sun2015$Set)
# Merge with your date
sun2015$day_rise <- as.POSIXct(paste0(sun2015$Day, " ",sun2015$Rise), format = "%m/%d/%Y %H%M", origin = "1970-01-01", tz = "UTC")
sun2015$day_set <- as.POSIXct(paste0(sun2015$Day, " ",sun2015$Set), format = "%m/%d/%Y %H%M", origin = "1970-01-01", tz = "UTC")
> sun2015$day_rise
[1] "2015-01-01 06:52:00 UTC" "2015-01-02 06:52:00 UTC" "2015-01-03 06:52:00 UTC" "2015-01-04 06:53:00 UTC"
[5] "2015-01-05 06:53:00 UTC"
> sun2015$day_set
[1] "2015-01-01 17:55:00 UTC" "2015-01-02 17:56:00 UTC" "2015-01-03 17:56:00 UTC" "2015-01-04 17:57:00 UTC"
[5] "2015-01-05 17:57:00 UTC"
You can adjust to the appropriate time zone if necessary.

R round a date with timezone

timestamp = 1491800340000
I'm having trouble with some date manipulation in R. The timestamp above is:
2017-04-10T04:59:00.000 GMT
2017-04-09T23:59:00.000 America/Bogota (Local time)
I want to round it to 2017-04-09T00:00:00.000 GMT because my daily aggregations are set to 00:00 GMT.
How can I do that?
Here's what I tried:
> Sys.timezone()
[1] "America/Bogota"
> timestamp = 1491800340000
> date = strptime(timestamp / 1000, "%s");
[1] "2017-04-09 23:59:00 COT"
> midnightLocal = trunc(date, "day");
[1] "2017-04-09 COT"
> midnightUTC = strptime(format(midnightLocal, "%Y-%m-%d"), "%Y-%m-%d", tz = "UTC");
[1] "2017-04-09 UTC"
> truncatedtimestamp = as.integer(format(midnightUTC, "%s"));
[1] 1491714000
which is 2017-04-09T05:00:00.000 GMT (not midnight as I expected). Looks like I failed to specify the timezone somewhere?
I tried many things like POSIXct but did not succeed.
Any hint is appreciated!
Cheers
ps: I'd prefer not to install any package
A little trickery:
timestamp = 1491800340000
ts <- as.POSIXct(timestamp / 1000, origin = "1970-01-01 00:00:00 GMT")
ts2 <- as.Date(trunc(ts, "day"))
attr(ts2, "tzone") <- "GMT"
format(ts2, "%Y-%m-%d %H:%M:%S %Z") # to prove it's midnight
# [1] "2017-04-09 00:00:00 UTC"
class(ts2)
# [1] "Date"
From here you have a couple of options: a little brute-force (numeric conversion) or perhaps the more time-friendly/safe way.
Brute-force numeric:
ts3a <- as.numeric(ts2) * 60*60*24
ts3a
# [1] 1491696000
as.POSIXct(ts3a, origin = "1970-01-01 00:00:00 GMT", tz = "GMT")
# [1] "2017-04-09 GMT"
Time-friendly/safe:
ts3b <- as.POSIXct(ts2)
attr(ts3b, "tzone") <- "GMT"
ts3b
# [1] "2017-04-09 GMT"
(Since they are POSIXct, it's showing the date only because it is midnight; you can easily prove it's correct.)

How to add the time to a date when using as.date?

I have measurements that were taken at this time: 13880 and they represent "days since 1970-01-01 00:00:00"
So now I want to know the dat and time:
as.Date(13880, origin="1970-01-01")
[1] "2008-01-02" # works fine
Now to add the time:
as.Date(13880, origin="1970-01-01",tz = "UTC", format="%Y/%m/%d %H:%M:%S")
[1] NA
or
as.POSIXct(13880, origin="1970-01-01")
[1] "1970-01-01 04:51:20 CET"
as.POSIXlt(13879, origin="1970-01-01")
[1] "1970-01-01 04:51:19 CET"
None of these worked for me. Any idea?
as.POSIXct(as.Date("1970-01-01") + 13880) # returns "2008-01-01 19:00:00 EST"
as.POSIXct(as.Date("1970-01-01") + 13880.5) # returns "2008-01-02 07:00:00 EST"
You can also set your time zone:
How to change the default time zone in R?
also: http://blog.revolutionanalytics.com/2009/06/converting-time-zones.html

Why is the epoch date correct, but does not work as an offset for POSIXct objects?

I have a vector of POSIXct objects:
> dates <- seq(as.POSIXct("2004-01-01", tz="EST"), as.POSIXct("2004-01-02", tz="EST"), as.difftime(6, units="hours"))
> dates
[1] "2004-01-01 00:00:00 EST" "2004-01-01 06:00:00 EST"
[3] "2004-01-01 12:00:00 EST" "2004-01-01 18:00:00 EST"
[5] "2004-01-02 00:00:00 EST"
I create an epoch variable that defines a POSIXct object for the UNIX epoch:
> epoch <- strptime("1970-01-01 00:00:00", "%Y-%m-%d %H:%M:%S", tz="EST")
> class(epoch)
[1] "POSIXct" "POSIXt"
> epoch
[1] "1970-01-01 EST"
I then loop through the dates vector and print out the value, offset from epoch:
> for (d in dates) { print(as.POSIXct(d, origin=epoch, tz="EST")) }
[1] "2004-01-01 05:00:00 EST"
[1] "2004-01-01 11:00:00 EST"
[1] "2004-01-01 17:00:00 EST"
[1] "2004-01-01 23:00:00 EST"
[1] "2004-01-02 05:00:00 EST"
There seems to be a five-hour offset error between the values in dates and the representation of those same values, relative to epoch.
There is a +5 hr difference between EST and UTC, but I specified the EST time zone for epoch with the tz option. Printing out epoch, there doesn't seem to be the time information, only the date.
Is there a bug with strptime or as.POSIXct, or am I calculating the offset or generating epoch incorrectly?
As mentioned in the answer to For loop style has effect on class coercion?, in the for loop, your dates are converted to numbers. That is the number of seconds since the "standard" epoch. This includes the 5 hour shift between EST and UTC. That is added as an offset to your epoch. See the source of as.POSIXct.numeric.
The following does work because it sets up dates which will be the right number of seconds when converted to numeric.
dates <- seq(as.POSIXct("2004-01-01", tz="UTC"),
as.POSIXct("2004-01-02", tz="UTC"),
as.difftime(6, units="hours"))
epoch <- strptime("1970-01-01 00:00:00", "%Y-%m-%d %H:%M:%S", tz="EST")
for (d in dates) { print(as.POSIXct(d, origin=epoch, tz="EST")) }
Which gives
[1] "2004-01-01 EST"
[1] "2004-01-01 06:00:00 EST"
[1] "2004-01-01 12:00:00 EST"
[1] "2004-01-01 18:00:00 EST"
[1] "2004-01-02 EST"

Resources