lubridate parse_date_time() in R: Multi-Format Parser
lubridate parse_date_time() parses date strings when the format varies between rows or is unknown ahead of time. The orders argument accepts one or more format tokens and the function returns a POSIXct vector.
parse_date_time(x, orders = "ymd") # single format parse_date_time(x, orders = c("ymd","mdy","dmy")) # try several parse_date_time(x, orders = "ymd HMS") # with time parse_date_time(x, orders = "ymd", tz = "UTC") # with timezone parse_date_time(x, orders = "dmy", locale = "fr") # non-English parse_date_time(x, orders = "ymd", truncated = 2) # allow partial parse_date_time(x, orders = "ymd", exact = TRUE) # strict tokens
Need explanation? Read on for examples and pitfalls.
What parse_date_time() does in one sentence
parse_date_time(x, orders = ...) tries each format in orders until one parses successfully, then returns a POSIXct vector. Unlike ymd() and its sister functions, it does not assume a single format. You pass a list of possibilities and lubridate picks the first match per element.
This makes it the right tool whenever a column mixes formats, when source data quality is uncertain, or when locale and time-of-day pieces vary across rows.
Syntax: the orders argument
The orders argument is the single most important parameter. Pass a character string for a single format, or a character vector for several. Each token combines lubridate's letter codes for date pieces (y, m, d) and time pieces (H, M, S, I, p).
The order list is tried left to right. Put your most likely format first so most rows parse on the first attempt.
"ymd HMS" parses "2024-01-15 14:30:45" without splitting the string. Space inside the token matches one or more whitespace characters in the input.Five common parsing patterns
Five recurring patterns cover almost every real-world use case for parse_date_time(). Each one isolates a feature that the lighter ymd() family does not expose.
1. Multiple possible formats in one column
When source data comes from multiple producers, each row may use a different ordering. A vector of orders solves this in one call.
2. Dates plus times
H is 24-hour, I is 12-hour with p for AM/PM. Use M for minutes, S for seconds.
3. Set a timezone at parse time
Default is UTC. Pass tz = "America/New_York" (or any value from OlsonNames()) to interpret the string in a specific zone.
4. Non-English month names
locale = "fr_FR" swaps the month name dictionary. On Windows the locale string is OS specific ("French_France"); check Sys.getlocale() if the call errors.
5. Truncated dates
truncated = 2 lets the last 2 pieces of the order be missing. Missing pieces fill with sensible defaults (month 1, day 1, hour 0).
ymd_* function is essentially parse_date_time(x, orders = "ymd_*", quiet = TRUE). When the wrappers feel too restrictive, drop down to parse_date_time directly.parse_date_time vs ymd_* family: when each wins
The lubridate parser family is a stack. parse_date_time sits at the bottom; the named parsers wrap it for common cases. Pick the wrapper when the format is known and uniform; reach for parse_date_time when it is not.
| Use case | Right tool | Why |
|---|---|---|
| All rows use one known format | ymd(), mdy(), dmy() |
Shorter call, same speed |
| Mixed formats across rows | parse_date_time(orders = c(...)) |
Only function that tries multiple |
| Truncated dates ("2024", "2024-01") | parse_date_time(truncated = N) |
Wrappers fail on partial input |
| Non-English month names | parse_date_time(locale = ...) |
Wrappers use the system locale only |
| Excel serial numbers | as.Date(x, origin = ...) |
Not a string format |
| Strict format check | parse_date_time(exact = TRUE) |
Refuses any token deviation |
For the canonical reference on every parameter, see lubridate's parse_date_time documentation.
Common pitfalls
Pitfall 1: silent NA on failed rows. parse_date_time returns NA with a warning when a row matches no order. Check sum(is.na(result)) immediately after parsing or chain a stopifnot(!anyNA(result)) to fail loudly.
Pitfall 2: order priority matters. With orders = c("dmy", "mdy") and input "01/02/2024", parse_date_time returns Feb 1 because dmy matches first. Reverse the orders or be explicit about the source convention.
Pitfall 3: locale is OS dependent. "fr_FR" works on macOS and Linux; on Windows the same locale is named "French_France". Use Sys.getlocale() to see valid names on the current machine.
"ymd", the result includes a 00:00:00 time component. Cast with as.Date() if a pure Date is what downstream code expects.Try it yourself
Try it: Parse the three strings below into a single POSIXct vector. Each row uses a different ordering. Save the result to ex_dates.
Click to reveal solution
Explanation: Each input matches a different order. parse_date_time tries ymd first; rows that fail fall through to mdy, then dmy. All three land on the same POSIXct value.
Related lubridate functions
After mastering parse_date_time, look at:
ymd(),mdy(),dmy(): shorter syntax when the format is knownymd_hms(),ymd_hm(),ymd_h(): date plus time wrappersfast_strptime(): faster than parse_date_time when the format is fixedwith_tz(),force_tz(): convert or override a timezone after parsingyear(),month(),day(),wday(): extract components from the parsed resultfloor_date(),ceiling_date(): round to a unit
FAQ
What is the difference between parse_date_time and ymd in R?
ymd() accepts year-month-day input only; it errors or returns NA on other orderings. parse_date_time(x, orders = c("ymd", "mdy")) tries multiple formats and picks the first match. Use ymd when the format is known and uniform; use parse_date_time when rows may differ or the format is uncertain.
How do I parse dates with multiple formats in R?
Pass a character vector to the orders argument: parse_date_time(x, orders = c("ymd", "mdy", "dmy")). lubridate tries each order in turn for every element and returns the first successful parse. Put the most likely format first for best performance.
How do I parse non-English dates with lubridate?
Use the locale argument: parse_date_time(x, orders = "dmy", locale = "fr_FR") parses French month names. The exact locale string depends on the OS. On Windows try "French_France"; on macOS and Linux "fr_FR" works. Run Sys.getlocale() to see what is installed.
Why does parse_date_time return POSIXct instead of Date?
parse_date_time always returns POSIXct so it can carry time and timezone information uniformly. When you only need a Date, wrap the call in as.Date(). For example, as.Date(parse_date_time(x, "ymd")) gives a plain Date vector.
What does the truncated argument do in parse_date_time?
truncated = N lets the last N pieces of the order be missing from the input. With orders = "ymd" and truncated = 2, the strings "2024", "2024-01", and "2024-01-15" all parse, with missing pieces filling as month 1 and day 1. Use it when source rows have varying precision.