r as.Date returns previous day - r

as.Date(date1) is incorrectly returning the previous day.
I suspect it has got to do with time zones, but I am still learning the very basics of R so I have little chance of solving it on my own.
The code I use to produce this is:
> a <- (capital_paid_summary_per_loan$Arrears_Date[1])
> a
[1] "2015-08-31 SAST"
> as.Date(a)
[1] "2015-08-30"
>
As you can see, the date starts off to be "2015-08-31" but as.Date() changes it to one day prior.
Any advice is welcome

If
date <- "2015-08-31 SAST"
You could use:
as.Date("2015-08-31 SAST",tz='SAST')
Which specifies the timezone as SAST, or you could use:
as.Date(gsub(' SAST','',date))
Which will remove the timezone from part of the string and then convert to date.

Related

How to convert from CEST to UTC?

I want to convert number of days to date with time:
> 15525.1+as.Date("1970-01-01")
[1] "2012-07-04" ## correct but no time
I tried this:
> apollo.fmt <- "%B %d, %Y, %H:%M:%S"
> as.POSIXct((15525.1+as.Date("1970-01-01")), format=apollo.fmt, tz="UTC")
[1] "2012-07-04 04:24:00 CEST"
but as you see the results provide in CEST. But I need it it in UTC.
Any hints on this?
For the original conversion, refer to this question: Converting numeric time to datetime POSIXct format in R and these pages: Date-times in R , Date-time conversions and Converting excel dates (number) to R date-time object. Bascially, it depends on your data source, the time origin for that data sources (Excel, Apache etc.) and the units. For example, you may have the total time elapsed in seconds, minutes, hours or days since the time origin for your data source which will be different for Excel or Apache. Once you have this information, you can use strptime or origin arguments and convert to R date-time objects.
If you are only concerned with changing the timezone, you can use attr:
> u <- Sys.time()
> u
[1] "2017-12-21 09:01:35 EST"
> attr(u, "tzone") <- "UTC"
> u
[1] "2017-12-21 14:01:35 UTC"
You may want to check up on the valid timezones for your machine though. A good way to get a time-zone that works with your machine would be googleway::google_timezone. To get the coordinates for your location (or the location from where you're importing data), you can either look those up online or use ggmap::geocode() - useful if converting time stamps in data from different time zones.
I think the problem is as.POSIXct doesn't change anything if the time is already POSIXct, so the tz option has no effect.
Use attr as explained here

Formatting Unconventional Date

I'm having trouble formatting a list of dates in R. The conventional methods of formatting in R such as as.Date or as.POSIXct don't seem to be working.
I have dates in the format: 1012015
using
as.POSIXct(as.character(data$Start_Date), format = "%m%d%Y")
does not give me an error, but my date returns
"0015-10-12" because the month is not a two digit number.
Is there a way to change this into the correct date format?F
The lubridate package can help with this:
lubridate::mdy(1012015)
[1] "2015-01-01"
The format looks ambiguous but the OP gave two hints:
He is using format = "%m%d%Y" in his own attempt, and
he argues the issue is because the month is not a two digit number
This uses only base R. The %08d specifies a number to be formatted into 8 characters with 0 fill giving in this case "01012015".
as.POSIXct(sprintf("%08d", 1012015), format = "%m%d%Y")
## [1] "2015-01-01 EST"
Note that if you don't have any hours/minutes/seconds it would be less error prone to use "Date" class since then the possibility of subtle time zone errors is eliminated.
as.Date(sprintf("%08d", 1012015), format = "%m%d%Y")
## [1] "2015-01-01"

How to convert times over 24:00:00 in R

In R I have this data.frame
24:43:30 23:16:02 14:05:44 11:44:30 ...
Note that some of the times are over 24:00:00 ! In fact all my times are within 02:00:00 to 25:59:59.
I want to subtract all entries in my dataset data with 2 hours. This way I get a regular data-set. How can I do this?
I tried this
strptime(data, format="%H:%M:%S") - 2*60*60
and this work for all entries below 23:59:59. For all entries above I simply get NA since the strptime command produce NA to all entries above 23:59:59.
Using lubridate package can make the job easier!
> library(lubridate)
> t <- '24:43:30'
> hms(t) - hms('2:0:0')
[1] "22H 43M 30S"
Update:
Converting the date back to text!
> substr(strptime(hms(t) - hms('2:0:0'),format='%HH %MM %SS'),12,20)
[1] "22:43:30"
Adding #RHertel's update:
format(strptime(hms(t) - hms('2:0:0'),format='%HH %MM %SS'),format='%H:%M:%S')
Better way of formating the lubridate object:
s <- hms('02:23:58) - hms('2:0:0')
paste(hour(s),minute(s),second(s),sep=":")
"0:23:58"
Although the answer by #amrrs solves the main problem, the formatting could remain an issue because hms() does not provide a uniform output. This is best shown with an example:
library(lubridate)
hms("01:23:45")
#[1] "1H 23M 45S"
hms("00:23:45")
#[1] "23M 45S"
hms("00:00:45")
#[1] "45S"
Depending on the time passed to hms() the output may or may not contain an entry for the hours and for the minutes. Moreover leading zeros are omitted in single-digit values of hours, minutes and seconds. This can result pretty much in a formatting nightmare if one tries to put that data into a common form.
To resolve this difficulty one could first convert the time into a duration with lubridate's as.duration() function. Then, the duration in seconds can be transformed into a POSIXct object from which the hours, minutes, and seconds can be extracted easily with format():
times <- c("24:43:30", "23:16:02", "14:05:44", "11:44:30", "02:00:12")
shifted_times <- hms(times) - hms("02:00:00")
format(.POSIXct(as.duration(shifted_times),tz="GMT"), "%H:%M:%S")
#[1] "22:43:30" "21:16:02" "12:05:44" "09:44:30" "00:00:12"
The last entry "02:00:12" would have caused difficulties if shifted_times had been passed to strptime().

R Change date YY-MM-DD hh:mm to time since origin (Days.Seconds)

I have a date input like this (currently as character class):
input=c("2013-05-08 11:20:10", "2013-05-08 11:21:09")
And want to have an output like this:
output=c(127.472338, 127.473032)
Which is the time since origin (2013-01-01 00:00:00) in days and seconds.
Previously, I used data in the output format and reconverted it to the input format using:
temp=as.POSIXlt(output*24*3600,origin='2013-01-01 00:00:00', tz="Etc/GMT+0")
How can I rewrite this so that I get the desired output?
Thanks in advance.
Use difftime (or -):
> difftime(as.POSIXct(input), as.POSIXct("2013-01-01"))
Time differences in days
[1] 127.4307 127.4314
> as.POSIXct(input) - as.POSIXct("2013-01-01")
Time differences in days
[1] 127.4307 127.4314

Round an POSIXct date up to the next day

I have a question similar to Round a POSIX date (POSIXct) with base R functionality, but I'm hoping to always round the date up to midnight the next day (00:00:00).
Basically, I want a function equivalent to ceiling for POSIX-formatted dates. As with the related question, I'm writing my own package, and I already have several package dependencies so I don't want to add more. Is there a simple way to do this in base R?
Maybe
trunc(x,"days") + 60*60*24
> x <- as.POSIXct(Sys.time())
> x
[1] "2012-08-09 18:40:08 BST"
> trunc(x,"days")+ 60*60*24
[1] "2012-08-10 BST"
A quick and dirty method is to convert to a Date (which truncates the time), add 1 (which is a day for Date) and then convert back to POSIX to be at midnight UTC on the next day. As #Joshua Ulrich points out, timezone/daylight savings issues may give results you don't expect:
as.POSIXct(as.Date(Sys.time())+1)
[1] "2012-08-10 01:00:00 BST"

Resources