r-lib/clock

Handling Custom Time Format with Millisecond Precision

MarkusBerroth opened this issue · 2 comments

Hi,
I am currently encountering a situation where I need to parse a custom time format that includes milliseconds. The format I have is quite unusual and looks like this: "hour:minute:second AM/PM.millisecond". Here's an example:
"4/30/2023 9:00:00 AM.457"

I have also tried different solutions like
naive_time_parse( "4/30/2023 9:00:00 AM.457", format = "%m/%d/%Y %H:%M:%S %p.%0S", precision = "millisecond" )

However, I get always an error.
With Python, the following is working
datetime.strptime(stamp, "%m/%d/%Y %I:%M:%S %p.%f")
However, R and clock do not seem to have an %f placeholder.

My current solution is splitting the string and adding the milliseconds afterward:

time_parts <- unlist(strsplit("4/30/2023 9:00:00 AM.457", split = "\\.")) 
time_parts[1] %>%
  naive_time_parse(.,
    format = "%m/%d/%Y %I:%M:%S %p",
    precision = "millisecond"
  ) %>% 
  add_milliseconds(as.numeric(time_parts[2]))

However, I would prefer a solution that can handle this format directly, without the need for additional string manipulation or splitting.
Is there any built-in function in clock or an other package that can handle this custom format more conveniently? If not, would it be possible to add support for such custom formats in a future release or update?

Any guidance or suggestions would be greatly appreciated. Thank you for your time and effort in maintaining and improving this project!

I don't think you will find any package that can handle that correctly

The underlying <date.h> library assumes that seconds and subseconds are next to each other so that you can just parse them with %S along with precision = "millisecond", and that isn't going to change in the date library, so it is also unlikely to change in clock.

Another option is try to and swap them so the milliseconds are in the right spot

x <- c(
  "4/30/2023 9:00:00 AM.457",
  "4/30/2023 9:00:00 PM.457"
)

x <- x |>
  stringr::str_remove(" AM") |>
  stringr::str_remove(" PM") |>
  paste0(ifelse(stringr::str_detect(x, "AM"), " AM", " PM"))

x
#> [1] "4/30/2023 9:00:00.457 AM" "4/30/2023 9:00:00.457 PM"

clock::naive_time_parse(x, format = "%m/%d/%Y %I:%M:%S %p", precision = "millisecond")
#> <naive_time<millisecond>[2]>
#> [1] "2023-04-30T09:00:00.457" "2023-04-30T21:00:00.457"

Created on 2023-05-09 with reprex v2.0.2.9000

Thanks for the rapid response! Than some string manipulation will be the best option.