Extract Time (Hms) from Lubridate Date Time Object

Extract time (HMS) from lubridate date time object?

My solution is to install library(anytime):

date <- anytime::anydate(t)
time <- strftime(t, format="%H:%M:%S")

Extract date and time from datetime field in R

If I understood well, R can read correctly your dates and times as you import your data (because they are in POSIXct format), but you can not extract the date and the time in the right format from your date-time column.

Considering that you have a data.frame in R, like this:

            date_time Sold
1 2020-01-01 03:16:01 2
2 2020-01-02 02:15:12 2
3 2020-01-03 08:26:11 3
4 2020-01-04 09:29:14 2
5 2020-01-05 12:06:06 1
6 2020-01-06 08:08:11 3

Lubridate does not offer a function to extract the time component, so you have to extract piece by piece with the minute(), hour() and second() functions. Then you can just concatenate these components with paste() function. Now, with the dates, you can use the date() function to extract then, after that, you use the format() function to format these dates in the way you want.

library(lubridate)
library(dplyr)
library(magrittr)

tab <- tab %>%
mutate(
date = as.Date(date_time),
hour = hour(date_time),
minute = minute(date_time),
second = second(date_time)
) %>%
mutate(
format_date = format(date, "%m/%d/%Y"),
format_hour = paste(hour, minute, second, sep = ":")
)

Resulting this:

tab %>% select(format_date, format_hour) %>% head()

format_date format_hour
1 01/01/2020 12:4:23
2 01/02/2020 3:19:13
3 01/03/2020 8:6:24
4 01/04/2020 6:28:2
5 01/05/2020 2:16:20
6 01/06/2020 12:8:28

Date time conversion and extract only time

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.

datetime object to minutes: I need 3 packages

Here are two ways.

Base R

with(df, as.integer(format(dttm, "%M")) + 60*as.integer(format(dttm, "%H")))
#[1] 120 100 228 185 166

Another base R option, using class "POSIXlt" as proposed here.

minute_of_day <- function(x){
y <- as.POSIXlt(x)
60*y$hour + y$min
}

minute_of_day(df$dttm)
#[1] 120 100 228 185 166

Package lubridate

lubridate::minute(df$dttm) + 60*lubridate::hour(df$dttm)
#[1] 120 100 228 185 166

If the package is loaded, this can be simplified, with the same output, to

library(lubridate)
minute(df$dttm) + 60*hour(df$dttm)

extract time component (format - HH:MM:SS and HH:MM) from datetime

We may use format -

library(dplyr)
library(lubridate)

tbl %>%
mutate(round_reading = round_date(readings, unit = 'mins'),
hms = format(round_reading, '%T'),
hm = format(round_reading, '%H:%M'))

# readings round_reading hms hm
# <dttm> <dttm> <chr> <chr>
# 1 2018-01-05 12:00:15 2018-01-05 12:00:00 12:00:00 12:00
# 2 2018-01-01 02:00:15 2018-01-01 02:00:00 02:00:00 02:00
# 3 2018-02-25 12:00:15 2018-02-25 12:00:00 12:00:00 12:00
# 4 2018-04-15 11:00:15 2018-04-15 11:00:00 11:00:00 11:00
# 5 2020-10-15 10:00:15 2020-10-15 10:00:00 10:00:00 10:00
# 6 2019-10-20 08:00:15 2019-10-20 08:00:00 08:00:00 08:00
# 7 2019-11-15 02:01:15 2019-11-15 02:01:00 02:01:00 02:01
# 8 2018-11-02 11:00:15 2018-11-02 11:00:00 11:00:00 11:00
# 9 2018-07-09 02:00:15 2018-07-09 02:00:00 02:00:00 02:00
#10 2020-10-02 01:00:45 2020-10-02 01:01:00 01:01:00 01:01
#11 2020-01-29 02:00:55 2020-01-29 02:01:00 02:01:00 02:01
#12 2019-03-15 07:00:15 2019-03-15 07:00:00 07:00:00 07:00

Using lubridate to extract time periods from in R

The data sample databank[[1]] given in the actual question (here) is different from the situation in the referenced question Exclude specific time periods in R (there):

  1. The timestamp there had already been converted to class POSIXct while the Dateand Timehere are in separate factor columns.
  2. Here, Time uses a 12 hour clock with AM/PM indicator.

It might be possible to work with the factor levels of Time but this is unreliable. So, the safest way IMHO is to create a POSIXct timestamp from the Date and Time columns and to select by time of day (without date) later on.

Add time stamp

databank[[1L]]$datetime <- 
with(databank[[1L]], as.POSIXct(paste(Date, Time), "%d/%m/%Y %I:%M:%S %p", tz = "GMT"))

Add time of day

For convenience, a time_of_day (without date) column is added as character:

databank[[1L]]$time_of_day <- 
with(databank[[1L]], format(datetime, "%T"))

databank[[1L]][, c("Date", "Time", "datetime", "time_of_day")]
# Date Time datetime time_of_day
#1: 12/04/2017 10:45:43 AM 2017-04-12 10:45:43 10:45:43
#2: 12/04/2017 10:45:42 AM 2017-04-12 10:45:42 10:45:42
#3: 12/04/2017 10:45:41 AM 2017-04-12 10:45:41 10:45:41
#4: 12/04/2017 10:45:40 AM 2017-04-12 10:45:40 10:45:40
#5: 12/04/2017 10:45:39 AM 2017-04-12 10:45:39 10:45:39
#6: 12/04/2017 10:45:38 AM 2017-04-12 10:45:38 10:45:38
#7: 12/04/2017 10:45:00 PM 2017-04-12 22:45:00 22:45:00

Note that I've added a PM time for illustration.

Select rows by time of day range

databank[[1L]][time_of_day >= "09:35:00" & time_of_day < "15:55:00", ]

Lubridate hour() does not function with times derived from parse_date_time()

R doesn't have a native way to handle times that aren't associated to a day. But you can use a package like hms. For example:

library(tidyverse)
library(lubridate)
library(hms)

dt2 <- data.frame('date_time' = c("11/24/19 06:00:00 PM",
"11/25/19 12:00:00 AM",
"11/25/19 06:00:00 AM",
"11/25/19 12:00:00 PM",
"11/25/19 06:00:00 PM",
"11/26/19 12:00:00 AM"),
'date' = c(1:6), 'time' = c(1:6)) %>%
mutate(date_time = parse_date_time(date_time, orders = "mdy IMS %p"),
date = date(date_time),
time = as_hms(date_time),
hour = hour(time))

But to be honest, it's probably better to keep the date_time column and use hour directly on it.

Transform time - date to lubridate datetime object in R?

You just need to match the format of your date:

parse_date_time("23:46 13-08-2018", "H:M d-m-y")

Converting character timestamp to date-time stamp in R; H:M:S keeps getting removed

As pointed out in the comments, the problem is just how the data are printed. To convince yourself, just try to add 1 to the variable created by POSIXct:

timesdf<-structure(list(DateTime = c("2021-02-20 00:00:00", "2021-02-20 00:00:00", 
"2021-02-20 00:00:00", "2021-02-20 00:00:00", "2021-02-20 00:00:00",
"2021-02-20 00:00:00", "2021-02-20 00:00:00", "2021-02-20 00:00:00",
"2021-02-20 00:00:00", "2021-02-20 00:00:00", "2021-02-20 00:00:00",
"2021-02-20 00:00:00", "2021-02-20 00:00:00", "2021-02-20 00:00:00",
"2021-02-20 00:00:00")), row.names = c(NA, 15L), class = "data.frame")

library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union

timesdf <- timesdf |>
mutate(times = as.POSIXct(DateTime))

head(timesdf)
#> DateTime times
#> 1 2021-02-20 00:00:00 2021-02-20
#> 2 2021-02-20 00:00:00 2021-02-20
#> 3 2021-02-20 00:00:00 2021-02-20
#> 4 2021-02-20 00:00:00 2021-02-20
#> 5 2021-02-20 00:00:00 2021-02-20
#> 6 2021-02-20 00:00:00 2021-02-20

timesdf |>
mutate(times = times + 1) |>
head()
#> DateTime times
#> 1 2021-02-20 00:00:00 2021-02-20 00:00:01
#> 2 2021-02-20 00:00:00 2021-02-20 00:00:01
#> 3 2021-02-20 00:00:00 2021-02-20 00:00:01
#> 4 2021-02-20 00:00:00 2021-02-20 00:00:01
#> 5 2021-02-20 00:00:00 2021-02-20 00:00:01
#> 6 2021-02-20 00:00:00 2021-02-20 00:00:01

Created on 2021-09-16 by the reprex package (v2.0.1)

The errors you get from your POSIXct command ("unknown time zone") is due to the fact that the second argument to the POSIXct function is tz, as you see from the code above you don't have to specify the format.



Related Topics



Leave a reply



Submit