Skip to content

Tools for decomposing a datetime into date + hms + timezone and back #113

@krlmlr

Description

@krlmlr

Whenever I need to work with date-times and want to split the data into a date and its time component, I feel frustrated because the existing tools I'm familiar with (lubridate, clock) make this task quite difficult. Perhaps I'm missing something.

I think hms could offer lightweight tools for splitting and recombining, e.g., hms_separate() and hms_unite() . The result of hms_separate() would be a three-column tibble with components:

  • date: Date
  • time: hms
  • tz: the "zone", "isdst" and "gmtoff" components from POSIXlt

This implementation would be oblivious of leap seconds and such, but instead aim at being "good enough" for most practical cases.

The experiment below demonstrates a roundtrip for this decomposition for a timespan of over four years, with at least one timepoint in each hour.

ct <- structure(1675058104.91011, class = c("POSIXct", "POSIXt"), tzone = "") - seq(0, 14e7, by = 59)
# ct <- ct[2213:2217]
# ct <- head(ct, 100)

ct[[1]]
#> [1] "2023-01-30 06:55:04 CET"

t <- as.POSIXlt(ct)

# Get components that are sufficient for a roundtrip
tp <- hms::as_hms(t)
dp <- as.Date(t)
tzp <- unclass(t)[c("zone", "isdst", "gmtoff")]

# Helper
tp_decompose <- function(x) {
  x <- as.numeric(x)

  seconds <- x %% 60
  x <- x - seconds
  x <- as.integer(round(x / 60))

  minutes <- as.integer(round(x %% 60))
  x <- x - minutes
  x <- as.integer(round(x / 60))

  hours <- x

  list(hour = hours, min = minutes, sec = seconds)
}

# Implement roundtrip
tpd <- tp_decompose(tp)

ptt <- as.POSIXlt(dp)
attr(ptt, "tzone") <- attr(t, "tzone")

ptt <- unclass(ptt)
ptt[names(tpd)] <- tpd
ptt[names(tzp)] <- tzp
class(ptt) <- c("POSIXlt", "POSIXt")

# Check roundtrip
identical(t, ptt)
#> [1] TRUE

tt <- as.POSIXct(ptt)
identical(ct, tt)
#> [1] TRUE

Created on 2023-01-30 with reprex v2.0.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions