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):
- The
timestamp
there had already been converted to classPOSIXct
while theDate
andTime
here are in separatefactor
columns. - 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
How to Count Sequences of Ones in a Logical Vector
R Reshape2 'Aggregation Function Missing: Defaulting to Length'
Percentage of Overlap Between Polygons
How to Calculate the Median on Grouped Dataset
How to Get Dimnames in Xtable.Table Output
Applying Over a Vector of Functions
R: Save All Data.Frames in Workspace to Separate .Rdata Files
Error: Object '.Dosnowglobals' Not Found
How to Find Which Polygon a Point Belong to via Sf
How to Convert a Hex String to Text in R
Ggplot Inserting Space Before Degree Symbol on Axis Label
Adding Missing Dates to Dataframe
Greek Letters in Ggplot Strip Text
How to Search for a String in One Column in Other Columns of a Data Frame