18

I need to parse times in a character format like "1:36:22 PM".

I've tried various permutations of as.POSIXct and strptime but just can't get there. For example, this fails to pick up the importance of PM:

t <- "1:36:22 PM"
as.POSIXct(t, format = "%H:%M:%S")
# [1] "2016-09-08 01:36:22 BST"

and this fails:

strptime(t, "%H:%M:%S")
# [1] NA

Curiously, for reasons I can't understand, dropping the seconds from the input may work:

t <- "1:30:00 PM"
strptime(t, "%I:%M %p")
# [1] NA
 
t <- "1:30 PM"
strptime(t, "%I:%M %p")
# [1] "2016-09-08 13:30:00 BST"

All I want is for this to work:

t <- "1:30:00 PM"
SOME COMMAND HERE HERE
# [1] "13:30:00"

Any ideas?

Henrik
  • 65,555
  • 14
  • 143
  • 159
IanW
  • 301
  • 1
  • 2
  • 4

2 Answers2

15

Have you tried using the lubridate package? It can handle AM/PM using the %p indicator in the "parse_date_time" function.

library(lubridate)
t <- "1:36:22 PM"
parse_date_time(t, '%I:%M:%S %p')
[1] "2016-09-08 13:36:22 UTC"

From the lubridate documentation:

%I: Hours as decimal number (01–12 or 1–12).

%M: Minute as decimal number (00–59 or 0–59).

%S: Second as decimal number (00–61 or 0–61).

%P: AM/PM indicator in the locale. Used in conjunction with I and not with H. An empty string in some locales.

gillespiecd
  • 189
  • 4
  • 5
    These abbreviations are part of base R. See the documentation for `strptime` to see all the date-time abbreviations available. – aosmith Sep 08 '16 at 21:02
  • 2
    In `parse_date_time` you don't need the `%` symbols; [it ignores them anyway](http://stackoverflow.com/documentation/r/1157/date-and-time/7018/parsing-dates-and-datetimes-from-strings-with-lubridate#t=201609082306537640757). – alistaire Sep 08 '16 at 23:08
  • using the command `ymd_hms` from `lubridate`, you don't even need to specify the formatting as long as you enter a reasonable date time value. It automatically converts from AM/PM to 24hr time. – user3386170 Jan 20 '20 at 22:42
11

Use the conversion specifications %I and %p. See Details section in ?strptime:

%I Hours as decimal number (01–12).>

%p AM/PM indicator in the locale. Used in conjunction with %I and not with %H.

strptime(t, "%I:%M:%S %p")
Henrik
  • 65,555
  • 14
  • 143
  • 159
Shenglin Chen
  • 4,504
  • 11
  • 11
  • 1
    This answer turned up in the low quality review queue, presumably because you don't provide any explanation of the code. If this code answers the question, consider adding adding some text explaining the code in your answer. This way, you are far more likely to get more upvotes — and help the questioner learn something new. – lmo Sep 08 '16 at 22:04
  • 1
    ... also, it looks like you have `%l` (lower-case L) rather than `%I` (upper-case I) in your answer – Ben Bolker Sep 08 '16 at 22:11