Date time conversion and extract only time

50,512

Solution 1

If your data is

a <- "17:24:00"

b <- strptime(a, format = "%H:%M:%S")

you can use lubridate in order to have a result of class integer

library(lubridate)
hour(b)
minute(b)

# > hour(b)
# [1] 17
# > minute(b)
# [1] 24


# > class(minute(b))
# [1] "integer"

and you can combine them using

# character
paste(hour(b),minute(b), sep=":")

# numeric
hour(b) + minute(b)/60

for instance.

I would not advise to do that if you want to do any further operations on your data. However, it might be convenient to do that if you want to plot the results.

Solution 2

A datetime object contains date and time; you cannot extract 'just time'. So you have to think throught what you want:

  • POSIXlt is a Datetime representation (as a list of components)
  • POSIXct is a different Datetime representation (as a compact numeric)

Neither one omits the Date part. Once you have a valid object, you can choose to display only the time. But you cannot make the Date part disappear from the representation.

Solution 3

You can also use the chron package to extract just times of the day:

library(chron) 

# current date/time in POSIXt format as an example
timenow <- Sys.time()

# create chron object "times"
onlytime <- times(strftime(timenow,"%H:%M:%S"))

> onlytime
[1] 14:18:00
> onlytime+1/24
[1] 15:18:00
> class(onlytime)
[1] "times"

Solution 4

A "modern" tidyverse answer to this is to use hms::as_hms()

For example

library(tidyverse)
library(hms)

as_hms(1)
#> 00:00:01
as_hms("12:34:56")
#> 12:34:56

or, with your example data:

x <- as.POSIXlt(c("17:24:00", "17:25:00", "17:26:00", "17:27:00"), format = "%H:%M:%S")

x
#>[1] "2021-04-10 17:24:00 EDT" "2021-04-10 17:25:00 EDT" "2021-04-10 17:26:00 EDT" "2021-04-10 17:27:00 EDT"

as_hms(x)
# 17:24:00
# 17:25:00
# 17:26:00
# 17:27:00

See also docs here: https://hms.tidyverse.org/reference/hms.html

Solution 5

This is my idiom for getting just the timepart from a datetime object. I use floor_date() from lubridate to get midnight of the timestamp and take the difference of the timestamp and midnight of that day. I create and store a hms object provided with lubridate (I believe) in dataframes because the class has formatting of hh:mm:ss that is easy to read, but the underlying value is a numeric value of seconds. Here is my code:

library(tidyverse)
library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#> 
#>     date

# Create timestamps
#
# Get timepart by subtacting the timestamp from it's floor'ed date, make sure
# you convert to seconds, and then cast to a time object provided by the
# `hms` package.
# See: https://www.rdocumentation.org/packages/hms/versions/0.4.2/topics/hms
dt <- tibble(dt=c("2019-02-15T13:15:00", "2019-02-19T01:10:33") %>% ymd_hms()) %>%
  mutate(timepart = hms::hms(as.numeric(dt - floor_date(dt, "1 day"), unit="secs")))

# Look at result
print(dt)
#> # A tibble: 2 x 2
#>   dt                  timepart
#>   <dttm>              <time>  
#> 1 2019-02-15 13:15:00 13:15   
#> 2 2019-02-19 01:10:33 01:10

# `hms` object is really a `difftime` object from documentation, but is made into a `hms`
# object that defaults to always store data in seconds.
dt %>% pluck("timepart") %>% str()
#>  'hms' num [1:2] 13:15:00 01:10:33
#>  - attr(*, "units")= chr "secs"

# Pull off just the timepart column
dt %>% pluck("timepart")
#> 13:15:00
#> 01:10:33

# Get numeric part.  From documentation, `hms` object always stores in seconds.
dt %>% pluck("timepart") %>% as.numeric()
#> [1] 47700  4233

Created on 2019-02-15 by the reprex package (v0.2.1)

Share:
50,512

Related videos on Youtube

Antex
Author by

Antex

Updated on April 11, 2021

Comments

  • Antex
    Antex about 3 years

    Want to change the class for Time to POSIXlt and extract only the hours minutes and seconds

    str(df3$Time)
    chr [1:2075259] "17:24:00" "17:25:00" "17:26:00" "17:27:00" ...
    

    Used the strptime function

    df33$Time <- strptime(df3$Time, format = "%H:%M:%S") 
    

    This gives the date/time appended

    > str(df3$Time)
     POSIXlt[1:2075259], format: "2015-08-07 17:24:00" "2015-08-07 17:25:00" "2015-08-07 17:26:00" ...
    

    Wanted to extract just the time without changing the POSIXlt class. using the strftime function

    df3$Time <- strftime(df3$Time, format = "%H:%M:%S") 
    

    but this converts the class back to "char" -

    > class(df3$Time)
    [1] "character"
    

    How can I just extract the time with class set to POSIX or numeric...

  • Antex
    Antex almost 9 years
    Thanks for your prompt response Dirk. So can you give an example how to display just the HHMMSS in the data.frame?
  • Antex
    Antex almost 9 years
    Tried both - they both converted class back to character as stated above...That is the challenge .> str(df3) 'data.frame': 2075259 obs. of 9 variables: $ Date : Date, format: "2006-12-16" "2006-12-16" ... $ Time : chr "17:24:00" "17:25:00" "17:26:00" "17:27:00" ... $
  • Dirk Eddelbuettel
    Dirk Eddelbuettel almost 9 years
    I think you still don't understand. A Datetime object contains what it says. A short character string contains the formating. You can use the former to construct the latter. The latter will still not be a Datetime object.
  • Antex
    Antex almost 9 years
    I get what the datetime object is. Starting with char "17:20:00" I am using the strptime function to convert the class. But the function appends today's date str(df3$Time) $ Time : POSIXlt, format: "2015-08-07"2015-08-07 17:20:00" - I don't want today's date shown in the table. Just the time! My question again is not what is Datetime object, it is that why cant I just extract the HHMMSS WITHOUT changing the calss to character - are you saying that is just not possible?
  • Dirk Eddelbuettel
    Dirk Eddelbuettel almost 9 years
    Try format(Sys.time(), "%H%M%S") which, seconds ago, gave me "073007" as it is just past 7:30am where I live. And yes, that will give you character because that is what strftime() and format() return. Let's stop here and I suggest you step back and read up on the ample available documentation. Good luck.
  • Dirk Eddelbuettel
    Dirk Eddelbuettel almost 9 years
    You don't need lubridate to create an integer: as.integer(format(Sys.time(), "%H%M%S")) works just fine with base R functions.
  • rmuc8
    rmuc8 almost 9 years
    So why didn't you post it? That's part of the OP's question.
  • Antex
    Antex about 5 years
    Looking back, I could have articulated the question better. The question was posed when I had very little experience. But @mpettis answered the question just right. Thanks!
  • mpettis
    mpettis about 5 years
    Thanks! The way you originally posted is exactly how I had thought about it, so I don't have any criticisms about the phrasing. I posted this because I came to this post before I had an answer, wasn't completely happy with the other answers, found the hms package, and decided to leave this answer for posterity.