Extract time from timestamp? - r

Essentially, I want only the hour, minute, and seconds from a column of timestamps I have in R, because I want to view how often different data points occur throughout different times of day and day and date is irrelevant.
However, this is how the timestamps are structured in the dataset:
2008-08-07T17:07:36Z
And I'm unsure how to only get that time from this timestamp.
Thank you for any help you can provide and please just let me know if I can provide more information!

We can use strptime to convert to a datetime class and then format to extract the hour:min:sec.
dtime <- strptime(str1, "%Y-%m-%dT%H:%M:%SZ")
format(dtime, "%H:%M:%S")
#[1] "17:07:36"
If the OP wants to have the hour, min, sec as separate columns
read.table(text=format(dtime, "%H:%M:%S"), sep=":", header=FALSE)
# V1 V2 V3
#1 17 7 36
Another option is using lubridate
library(lubridate)
format(ymd_hms(str1), "%H:%M:%S")
#[1] "17:07:36"
data
str1 <- "2008-08-07T17:07:36Z"

Just
x <- '2008-08-07T17:07:36Z'
substr(x, 12, 19)
#[1] "17:07:36"
...will do it if the timestamp is consistent, which I imagine it would be given it is an ISO_8601 ( https://en.wikipedia.org/wiki/ISO_8601 ) string.

I think you are expecting this...
Sys.time()
[1] "2016-04-19 11:09:30 IST"
format(Sys.time(),format = '%T')
[1] "11:09:30"
if you want to give your own timestamp, then use bellow code:
format(as.POSIXlt("2016-04-19 11:02:22 IST"),format = '%T')
[1] "11:02:22"

A regular expression will probably be quite efficient for this:
x <- '2008-08-07T17:07:36Z'
x
## [1] "2008-08-07T17:07:36Z"
sub('.*T(.*)Z', '\\1', x)
## [1] "17:07:36"

Related

Converting numbers into time and date

I am trying to convert numeric values into times and dates. I am working with a data set so it would be appreciated if you should show an example using a dataset.
Here are some examples, converting 93537 into 09:35:57 (HH:MM:SS). Additionally, I need to convert 220703 into 22-07-03 (YY:MM:DD).
I will add an example of my code below:
CPLF_data$HMS <- substr(as.POSIXct(sprintf("%04.0f", CPLF_data$StartTime), format='%H%M%S'), 12, 16)
CPLF_data$YMD <- as.POSIXct(CPLF_data$Date, tz="UTC", origin ="1970-01-01", format ="%Y-%M-%D")
The first line is correct however, it does not show seconds.
The second line is incorrect.
Thank you.
I want my final product to be a new column with the times and dates in the correct format with their own columns.
Use chron times class to get the times or if a character string is wanted use as.character on that. Use as.Date to get a Date class object. The sub puts colons between the parts of the time after which we can convert it to times class. The sprintf pads the date with 0 on the left if it is only 5 characters and otherwise leaves it as 6 characters and then we convert that to Date class.
library(chron)
time <- 93537
date <- 220703
tt <- times(sub("(..)(..)$", ":\\1:\\2", time))
tt
## [1] "09:35:37"
as.character(tt)
## [1] "09:35:37"
dd <- as.Date(sprintf("%06d", date), "%y%m%d")
dd
## [1] "2022-07-03"
as.character(dd)
## [1] "2022-07-03"
Try the ymd_hms function in the lubridate package.
output$datetime <- ymd_hms(paste(input$year, input$month, input$day,
input$HH, input$MM, input$SS, sep="-"))
You can enter 00 if you don't have seconds, for example ....
Base R does not have a class for just "time" (of day), as.POSIXct doesn't deal with "times", it deals with "date-times". The lubridate:: package does give number-like HMS values, which may be relevant, but since each row has both date and time, it seems relevant to combine them instead of putting them into separate columns.
CPLF_data |>
transform(
StartTime = as.numeric(StartTime),
Date = as.numeric(Date)
) |>
transform(
DateTime = ISOdate(
2000 + Date %/% 10000, (Date %% 10000) %/% 100, Date %% 100,
StartTime %/% 10000, (StartTime %% 10000) %/% 100, StartTime %% 100)
)
# StartTime Date DateTime
# 1 93537 220703 2022-07-03 09:35:37
Note: I'm assuming that all years are 2-digits and at/after 2000. If this is not true, it's not difficult to work around it with some custom code. Also, over to you if you want to set the timezone of this timestamp by adding tz="US/Mountain" or whichever is more appropriate for the data.
Data
CPLF_data <- data.frame(StartTime = "93537", Date = "220703")

Difference of Dates in R [duplicate]

I have a date in R, e.g.:
dt = as.Date('2010/03/17')
I would like to subtract 2 years from this date, without worrying about leap years and such issues, getting as.Date('2008-03-17').
How would I do that?
With lubridate
library(lubridate)
ymd("2010/03/17") - years(2)
The easiest thing to do is to convert it into POSIXlt and subtract 2 from the years slot.
> d <- as.POSIXlt(as.Date('2010/03/17'))
> d$year <- d$year-2
> as.Date(d)
[1] "2008-03-17"
See this related question: How to subtract days in R?.
You could use seq:
R> dt = as.Date('2010/03/17')
R> seq(dt, length=2, by="-2 years")[2]
[1] "2008-03-17"
If leap days are to be taken into account then I'd recommend using this lubridate function to subtract months, as other methods will return either March 1st or NA:
> library(lubridate)
> dt %m-% months(12*2)
[1] "2008-03-17"
# Try with leap day
> leapdt <- as.Date('2016/02/29')
> leapdt %m-% months(12*2)
[1] "2014-02-28"
Same answer than the one by rcs but with the possibility to operate it on a vector (to answer to MichaelChirico, I can't comment I don't have enough rep):
R> unlist(lapply(c("2015-12-01", "2016-12-01"),
function(x) { return(as.character(seq(as.Date(x), length=2, by="-1 years")[2])) }))
[1] "2014-12-01" "2015-12-01"
This way seems to do the job as well
dt = as.Date("2010/03/17")
dt-365*2
[1] "2008-03-17"
as.Date("2008/02/29")-365*2
## [1] "2006-03-01"
cur_date <- str_split(as.character(Sys.Date()), pattern = "-")
cur_yr <- cur_date[[1]][1]
cur_month <- cur_date[[1]][2]
cur_day <- cur_date[[1]][3]
new_year <- as.integer(year) - 2
new_date <- paste(new_year, cur_month, cur_day, sep="-")
Using Base R, you can simply use the following without installing any package.
1) Transform your character string to Date format, specifying the input format in the second argument, so R can correctly interpret your date format.
dt = as.Date('2010/03/17',"%Y/%m/%d")
NOTE: If you look now at your enviroment tab you will see dt as variable with the following value "2010-03-17" (Year-month-date separated by "-" not by "/")
2) specify how many years to substract
years_substract=2
3) Use paste() combined with format () to only keep Month and Day and Just substract 2 year from your original date. Format() function will just keep the specific part of your date accordingly with format second argument.
dt_substract_2years<-
as.Date(paste(as.numeric(format(dt,"%Y"))-years_substract,format(dt,"%m"),format(dt,"%d"),sep = "-"))
NOTE1: We used paste() function to concatenate date components and specify separator as "-" (sep = "-")as is the R separator for dates by default.
NOTE2: We also used as.numeric() function to transform year from character to numeric

Convert a chr time in to actuall time in R

so I'm trying to convert a F1 Laptime that is written in a chr in to time which I can then plot into a histogram.
This is what i tried. But with no success.
lapTimes <- lapTimes %>% mutate(Time = ms(Time))
format(as.POSIXct(lapTimes$time, tz = ""), format = "%M:%S.%OS")
The time always looks like this 1:11.111, with minutes first then secunds and then milliseconds.
If anyone has a idea I would greatly apprichiate that.
Thanks in advance! :D
As stated previously, I am assuming your data looks something like this:
laptime <- c("1:11.111", "2:02.2222")
What this represents is a time interval not a date time. As such you can convert this to a difftime class and then to numeric if needed.
as.difftime(laptime, format = "%M:%S.%OS")
#Time differences in mins
#[1] 1.183333 2.033333
since you provided no example data, I assumed it is stored as a character.
laptime <- "1:11.111"
> as.POSIXlt.character(laptime, format = "%M:%S.%OS", tz = 'GMT')
[1] "2021-01-14 00:01:11 GMT"
# compute time difference from dates
laptime <- "1:11.111"
t2 <- as.POSIXlt.character(laptime, format = "%M:%S.%OS", tz = 'GMT')
t1 <- as.Date(t2)
> difftime(t2, t1)
Time difference of 1.183333 mins
You could also take a look at this link, looks very useful for your specific problem: https://rstudio-pubs-static.s3.amazonaws.com/276999_042092be8e31414f82ef4f41e31fe5c8.html

Converting dates before January 1, 1970 in R

I am trying to convert a column of dates into Date objects in R, but I can't seem to get the desired results. These individuals have birth dates before January 1, 1970, so when I use as.Date R converts a date like 1/12/54, for example, to 2054-01-12. How can I work around this? Thanks so much.
No need for add-on packages, base R is fine. But you need to specify the century:
R> as.Date("1954-01-12")
[1] "1954-01-12"
R>
If you need non-default formats, just specify them:
R> as.Date("19540112", "%Y%m%d")
[1] "1954-01-12"
R>
Edit: In case your data really comes in using the %y% format, and you happen to make the policy decision that the 19th century is needed
, here is one base R way of doing it:
R> d <- as.Date("540112", "%y%m%d")
R> dlt <- as.POSIXlt(d)
R> dlt$year <- dlt$year - 100
R> as.Date(dlt)
[1] "1954-01-12"
R>
If everything is in the 1900s, its a one-liner - just format it with a two-digit year at the start and slap a 19 on the front and convert to a date. Again. Man this would look cool some %>% stuff:
s = c("1/12/54","1/12/74")
as.Date(format(as.Date(s,format="%d/%m/%y"), "19%y%m%d"), "%Y%m%d")
# [1] "1954-12-01" "1974-12-01"
If years from "69" to "99" are 1800s, then here's another one-liner:
library(dplyr) # for pipe operator:
s %>% as.Date(format="%d/%m/%y") %>%
format("%y%m%d") %>%
(function(d){
paste0(ifelse(d>700101,"18","19"),d)
}) %>%
as.Date("%Y%m%d")
## [1] "1954-12-01" "1874-12-01"
Note not thoroughly tested so might be some off-by-one errors or I've mixed months and days because you need to be ISO8601 Compliant
I would do:
library(lubridate)
x <- as.Date("1/12/54", format = "%m/%d/%y")
year(x) <- 1900 + year(x) %% 100
> x
[1] "1954-01-12"

How to convert a date to YYYYDDD?

I can't figure out how to turn Sys.Date() into a number in the format YYYYDDD. Where DDD is the day of the year, i.e. Jan 1 would be 2016001 Dec 31 would be 2016365
Date <- Sys.Date() ## The Variable Date is created as 2016-01-01
SomeFunction(Date) ## Returns 2016001
You can just use the format function as follows:
format(Date, '%Y%j')
which gives:
[1] "2016161" "2016162" "2016163"
If you want to format it in other ways, see ?strptime for all the possible options.
Alternatively, you could use the year and yday functions from the data.table or lubridate packages and paste them together with paste0:
library(data.table) # or: library(lubridate)
paste0(year(Date), yday(Date))
which will give you the same result.
The values that are returned by both options are of class character. Wrap the above solutions in as.numeric() to get real numbers.
Used data:
> Date <- Sys.Date() + 1:3
> Date
[1] "2016-06-09" "2016-06-10" "2016-06-11"
> class(Date)
[1] "Date"
Here's one option with lubridate:
library(lubridate)
x <- Sys.Date()
#[1] "2016-06-08"
paste0(year(x),yday(x))
#[1] "2016160"
This should work for creating a new column with the specified date format:
Date <- Sys.Date
df$Month_Yr <- format(as.Date(df$Date), "%Y%d")
But, especially when working with larger data sets, it is easier to do the following:
library(data.table)
setDT(df)[,NewDate := format(as.Date(Date), "%Y%d"
Hope this helps. May have to tinker if you only want one value and are not working with a data set.

Resources