R convert time format 130800Z - Day, Hour, Min - r

I am calling an api that returns the time in the format 130800Z which represents The day, hour and minutes. I'm wonder if there is an easy way to convert this?
My approach would be string splitting Sys.Date to get the month and year, then splitting 130800Z by every 2 characters and merging all the results into 2017-10-13 08:00:00
Just wondering if there is a way to use striptime(sprintf(... without having to split anything?

Try this:
strptime(x = time,format = "%d%H%M",tz = "GMT")
#[1] "2017-10-13 08:00:00 GMT"

I did this but had to use splitting
time = "130950Z"
day = substring(time, seq(1,nchar(time),2), seq(2,nchar(time),2))[1]
hour = substring(time, seq(1,nchar(time),2), seq(2,nchar(time),2))[2]
min = substring(time, seq(1,nchar(time),2), seq(2,nchar(time),2))[3]
year = unlist(str_split(Sys.Date(), "-"))[1]
month = unlist(str_split(Sys.Date(), "-"))[2]
dt = strptime(sprintf("%s-%s-%s %s:%s:%s", year, month, day, hour, min, 0), "%Y-%m-%d %H:%M:%S")
dt = "2017-10-13 09:50:00 GMT"

Related

How can I extract a specific range of hours from a dataframe in R

I have a data frame in R with 2 columns (date_time , temp) I want to extract all the temp for the day time (between 5:59 Am to 18:00 Pm). I firstly separated date and times(hours) with this code:
Th$Hours <- format(as.POSIXct(Th$`date`,
"%Y-%m-%d %H:%M:%S", tz = ""),
format = "%H:%M")%>% as_tibble()
Th$Dates <- format(as.Date(Th$`date`,"%Y-%m-%d",
tz = ""), format = "%Y-%m-%d")%>% as_tibble()
and then I use following command to extract specific times:
Th_day<- Th[Th$Hours >= " 06:00 AM" & Th$Hours<= "18:00 PM",]%>% as_tibble()
But I get a tibble that give rows from 00:00 to 18:00 for every day :
What is the problem ?
Don't separate out the date from the time. When you use format to get the time, you are converting it to a character class, that doesn't know how to do time-based comparisons with > and <.
Instead, use hour to extract the hour component as an integer, and do comparisons on that:
library(lubridate)
Th %>%
mutate(DateTime <- as.POSIXct(date, "%Y-%m-%d %H:%M:%S", tz = "")) %>%
filter(hour(DateTime) >= 6 & hour(DateTime ) < 18)
I'm making some assumptions about your data structure - if you need more help than this please edit your question to share some sample data with dput() as the commenters have requested. dput(Th[1:5, ]) should be plenty.
Note that if you want to do a lot of operations on just the times (ignoring the date part), you could use the times class from the chron package, see here for some more info.

How to format a time in R

I have been given a dataset that lists date and time separately. The dates are fine however the time is being treated as a character rather than a date/time object.
The current time column looks like "13:00", "13:05", "13:10" etc.
I tried mutating the column using as.POSIXct() however it changed the column to all NA.
This was my attempt:
data = data %>%
mutate(time = as.POSIXct(time, format = "h:m"))
I expected a similar looking column but instead of strings I wanted it to be times/dates. Thanks for any help!
The times class in chron can represent times without dates:
library(chron)
library(dplyr)
# input data
data <- data.frame(date = "2000-01-01", time = c("13:00", "13:05", "13:10"))
data %>%
mutate(date = as.chron(as.character(date)),
time = times(paste0(time, ":00")),
datetime = chron(date, time))
giving:
date time datetime
1 01/01/00 13:00:00 (01/01/00 13:00:00)
2 01/01/00 13:05:00 (01/01/00 13:05:00)
3 01/01/00 13:10:00 (01/01/00 13:10:00)
For a simple, non package solution:
I would first create a column with both the date and time in it
dateandtime <- as.character(paste(date, time, sep = ' '))
and then use the strptime function:
dateandtime <- strptime(dateandtime,
format = "%Y-%m-%d %H:%M",
tz = 'GMT')
just put the dataframe name in front of all variables, e.g.:
df$dateandtime <- as.character(paste(df$date, df$time, sep = ' '))
Hope it helps!
If you use as.POSIXct, you need to provide the format differently:
as.POSIXct("13:05", format = "%H:%M")
This however returns [1] "2019-03-26 13:05:00 CET" since date/times are represented as calendar dates plus time to the nearest second.
If you only want to use the time, you could use data.table::asITime:
data.table::as.ITime(c("13:00", "13:05", "13:10"))
This returns:
str(data.table::as.ITime(c("13:00", "13:05", "13:10")))
'ITime' int [1:3] 13:00:00 13:05:00 13:10:00

Duration in seconds since midnight on specific day

Say I have a start date and time "2016-01-09 15:23:26" and measurements taken at varying intervals with the date and time recorded for each measurement.
Sample data follow:
date time date_time clock
"2016-01-09" "15:23:26" 2016-01-09 15:23:2 0s (0 seconds)
"2016-01-10" "23:59:53" 2016-01-09 23:59:53 30987s (~8.61 hours)
"2016-01-10" "00:04:53" NA NA
"2016-01-10" "01:04:55" 2016-01-10 01:04:55 34889s (~9.69 hours)
If I try to use lubridate to calculate the duration, in minutes since the start time, the calculation works fine for all but row 3 (where the date is "2016-01-10" and the time is "00:04:53". I've tried to look on the web for some possible explanation for what is going wrong here but to no avail. What am I missing? My code follows:
library(lubridate)
df$date2 = mdy(df$Date)
df$time2 = hms(df$Time)
df$date_time = paste(df$date2, df$time2, sep = " ")
df$date_time = ymd_hms(df$date_time)
df$start_time = ymd_hms("2016-01-09 15:23:26", tz="UTC")
df$clock = as.duration(df$date_time - df$start_time)
When you paste date and time, because third time is less than an hour, it is not recognized by ymd_hms()
Since you already have POSIXct objects, you can sum them directly.
Simply replace :
df$date_time = paste(df$date2, df$time2, sep = " ")
df$date_time = ymd_hms(df$date_time)
by:
df$date_time = df$date2+df$time2

R package constructing time objects from date and hour(integer)

I have data provided in the form of a date telling the day (format "YYYY-MM-DD", e.g. "2015-03-11" and the hours of the day numbered (0-23).
What is the most convenient way to produce time objects of the form
"2015-03-11" and hour = 0 -> "2015-03-11 00:00"
"2015-03-11" and hour = 1 -> "2015-03-11 01:00"
"2015-03-11" and hour = 2 -> "2015-03-11 02:00"
I could use the Date function from Base or something from xts or timeDate.
Should be easy but I am sure someone out there knows it quickly.
EDIT: the data is provided in 2 columns, one for the date and one numerical.
You don't need an external package to do that.
If your data is in this format:
df=data.frame(date=c("2015-03-11","2015-03-11","2015-03-11"),hour=0:2)
just apply the following function:
format(as.POSIXct(df$date)+df$hour*60*60, format = "%Y-%m-%d %H:%M")
Suppose we have this input:
date <- c("2015-03-11", "2015-03-12")
hour <- 2:3
then try one of these:
1) chron
library(chron)
as.chron(date) + hour/24
giving:
[1] (03/11/15 02:00:00) (03/12/15 03:00:00)
2) POSIXct. This one only uses the base of R, no packages:
as.POSIXct(date) + 3600 * hour
giving, on my system:
[1] "2015-03-11 02:00:00 EDT" "2015-03-12 03:00:00 EDT"
If you wanted the result in the UTC time zone use:
as.POSIXct(date, tz = "UTC") + 3600 * hour
3) lubridate
library(lubridate)
ymd(date) + hours(hour)
giving:
[1] "2015-03-11 02:00:00 UTC" "2015-03-12 03:00:00 UTC"
If you want it in the current time zone then:
ymd(date, tz = "") + hours(hour)
Note that the chron solution gives a date/time class that does not use time zones eliminating the many problems that time zones can cause. The POSIXct and lubridate solutions give the date/time in a specific time zone as shown.
You could try
dtime <- with(df, as.POSIXct(sprintf('%s %02d', date, hour),
format = "%Y-%m-%d %H"))
and then use format as in the other posts
Or
library(lubridate)
ymd_h(with(df, sprintf('%s %02d', date, hour)))
Or slightly more compact
ymd_h(do.call(paste, df))
Try this. You can format it without seconds afterwards using format if you wish, though I think it is preferable to keep it in POSIXct class so you can manipulate it afterwords (adding removing days, seconds, etc.)
as.POSIXct(do.call(paste, df), format = "%Y-%m-%d %H")
## [1] "2015-03-11 00:00:00 IST" "2015-03-11 01:00:00 IST" "2015-03-11 02:00:00 IST"
Though, If you insist on your exact output, here's the solution with format
format(as.POSIXct(do.call(paste, df), format = "%Y-%m-%d %H"), "%Y-%m-%d %H:%M")
## [1] "2015-03-11 00:00" "2015-03-11 01:00" "2015-03-11 02:00"
Data
df <- structure(list(V1 = structure(c(1L, 1L, 1L), .Label = "2015-03-11", class = "factor"),
V2 = 0:2), .Names = c("V1", "V2"), class = "data.frame", row.names = c(NA,
-3L))

Convert julian time into date in R

I am trying to convert an array of Julian time into the standard Gregorian calendar. For that, I am using chron, which seems quite simple. The problem is that the origin does not fit with the beginning of the time. That means, I know the date starts at 12:00:00 in 23 May 2014 and end at 5th Sep 2014 at 7am. Then, if I use chron as the following:
#The first 50 values
time <- dput(t[1:50])
structure(c(143.0208333, 143.0416667, 143.0625, 143.0833333,
143.1041667, 143.125, 143.1458333, 143.1666667, 143.1875, 143.2083333,
143.2291667, 143.25, 143.2708333, 143.2916667, 143.3125, 143.3333333,
143.3541667, 143.375, 143.3958333, 143.4166667, 143.4375, 143.4583333,
143.4791667, 143.5, 143.5208333, 143.5416667, 143.5625, 143.5833333,
143.6041667, 143.625, 143.6458333, 143.6666667, 143.6875, 143.7083333,
143.7291667, 143.75, 143.7708333, 143.7916667, 143.8125, 143.8333333,
143.8541667, 143.875, 143.8958333, 143.9166667, 143.9375, 143.9583333,
143.9791667, 144, 144.0208333, 144.0416667), .Dim = 50L)
#Convert into GCalen.
newtime <- chron(time, origin=c(month = 1, day = 1, year = 2014))
dates <- as.POSIXlt(newt, "GMT")
The dates start at:
"2014-05-24 00:29:59 GMT" "2014-05-24 01:00:00 GMT" "2014-05-24 01:30:00 GMT" "2014-05-24 01:59:59 GMT"....
Looking into the end of the dates, I would have the same problem, because it finishes at "2014-09-06 07:30:00 GMT", one day later ..so there is a substantial lapse that it needs to be fixed.
is there any way to add in the origin the time?? hour:min:sg??

Resources