4

I am wondering if I am missing something?!

I would like to know: is there a better/shorter way to get minutes from a datetime object:

Lessons studied so far:

Extract time (HMS) from lubridate date time object?

converting from hms to hour:minute in r, or rounding in minutes from hms

R: Convert hours:minutes:seconds

My tibble:

df <- structure(list(dttm = structure(c(-2209068000, -2209069200, -2209061520, 
-2209064100, -2209065240), tzone = "UTC", class = c("POSIXct", 
"POSIXt"))), row.names = c(NA, -5L), class = c("tbl_df", "tbl", 
"data.frame"))

# A tibble: 5 x 1
  dttm               
  <dttm>             
1 1899-12-31 02:00:00
2 1899-12-31 01:40:00
3 1899-12-31 03:48:00
4 1899-12-31 03:05:00
5 1899-12-31 02:46:00

I would like to add a new column with minutes as integer:

My approach so far:

library(dplyr)
library(lubridate)  # ymd_hms
library(hms)        # as_hms
library(chron)      # times

test %>% 
    mutate(dttm_min = as_hms(ymd_hms(dttm)),
           dttm_min = 60*24*as.numeric(times(dttm_min)))

# A tibble: 5 x 2
  dttm                dttm_min
  <dttm>                 <dbl>
1 1899-12-31 02:00:00      120
2 1899-12-31 01:40:00      100
3 1899-12-31 03:48:00      228
4 1899-12-31 03:05:00      185
5 1899-12-31 02:46:00      166

This gives me the result I want, but I need for this operation 3 packages. Is there a more direct way?

TarJae
  • 72,363
  • 6
  • 19
  • 66
  • 2
    What's wrong with the [`as.POSIXlt` alternative you linked to](https://stackoverflow.com/a/29067449/1851712)? – Henrik Sep 12 '21 at 09:50
  • This is a very good answer. Therefore I linked this answer. Personally I really have problems to get `as.POSIXlt` in my brain. At least at this stage. So I was wondering to ask for alternative ways. I hope this is OK! – TarJae Sep 12 '21 at 09:56

4 Answers4

3

Here is a base R way -

You can extract the time using format, change the date to '1970-01-01' (Since R datetime starts with '1970-01-01'), convert to numeric and divide the time by 60 to get the duration in minutes.

as.numeric(as.POSIXct(paste('1970-01-01', format(df$dttm, '%T')), tz = 'UTC'))/60
#[1] 120 100 228 185 166
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • This is an excellent answer, that brings my knowledge further! I decided to accept Rui Barradas answer, as this fits more to my actual needs! – TarJae Sep 12 '21 at 09:59
1

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)
Rui Barradas
  • 70,273
  • 8
  • 34
  • 66
1

We can use

library(data.table)
 as.numeric(as.ITime(format(df$dttm, '%T')))/60
[1] 120 100 228 185 166
akrun
  • 874,273
  • 37
  • 540
  • 662
1

For sake of completeness, the time of day (in minutes) can be calculated by taking the difftime() between the POSIXct datetime object and the beginning of the day, e.g.,

difftime(df$dttm, lubridate::floor_date(df$dttm, "day"), units = "min")
Time differences in mins
[1] 120 100 228 185 166

Besides base R only one other package is required.

According to help("difftime"), difftime() returns an object of class "difftime" with an attribute indicating the units.

Uwe
  • 41,420
  • 11
  • 90
  • 134