readr parse_date() in R: Convert Strings to Date Objects

The readr parse_date() function converts a character vector into a proper Date object, using a format string of strptime-style codes so values like "15/03/2024" or "March 15, 2024" become the date 2024-03-15.

⚡ Quick Answer
parse_date("2024-03-15")                      # ISO default, no format needed
parse_date("15/03/2024", format = "%d/%m/%Y") # day-first
parse_date("03/15/2024", format = "%m/%d/%Y") # month-first (US)
parse_date("March 15, 2024", "%B %d, %Y")     # full month name
parse_date("15-Mar-24", "%d-%b-%y")           # abbreviated month, 2-digit year
parse_date("2024.03.15", "%Y.%m.%d")          # custom separator
parse_date(x, na = c("", "NA", "missing"))    # treat extra strings as NA

Need explanation? Read on for examples and pitfalls.

📊 Is parse_date() the right tool?
STARTparse a character column to datesparse_date(x, "%m/%d/%Y")parse date plus a clock timeparse_datetime(x, "%Y-%m-%d %H:%M")parse clock times onlyparse_time(x, "%H:%M")numbers with currency or commasparse_number(x)set column types during importread_csv(file, col_types = cols())guess the order without a formatlubridate::dmy(x)

What parse_date() does

parse_date() turns text into real dates. It takes a character vector and a format string, then returns a Date vector that R can sort, subtract, and plot on a time axis. A column read as "2024-03-15" is just text until you parse it; arithmetic and date filters only work on the parsed result.

The function lives in the readr package and is the same engine that fills date columns when you import a file. Calling it directly is useful when a column arrived as character, when the file used an unusual layout, or when you want to test a format before applying it to a whole dataset.

Key Insight
A date is a number, not a string. R stores a Date as the count of days since 1970-01-01. Once parse_date() does the conversion, date2 - date1 returns a day count and comparisons like date > "2024-01-01" work. That is the whole reason to parse rather than leave the column as text.

parse_date() syntax and arguments

The signature has five arguments, and only the first two matter day to day. You pass the character vector and, in almost every case, a format string describing how the text is laid out.

Run live
Run live, no install needed. Every R block on this page runs in your browser. Click Run, edit the code, re-run instantly. No setup.
Rparse_date function signature
library(readr) parse_date( x, # character vector to convert format = "", # strptime-style format codes na = c("", "NA"), # strings to treat as missing locale = default_locale(),# controls month and day names trim_ws = TRUE # strip surrounding whitespace )

  
Argument Purpose
x The character vector holding date text.
format Format codes such as %Y, %m, %d. Empty string means ISO 8601 only.
na Strings parsed as NA instead of dates.
locale Sets the language for month and weekday names.
trim_ws Removes leading and trailing spaces before parsing.

The common format codes are %Y (4-digit year), %y (2-digit year), %m (month number), %B (full month name), %b (abbreviated month name), and %d (day of month).

Examples by use case

The default call assumes ISO 8601. When format is empty, parse_date() only recognizes year-month-day text. This is the safest layout and needs no format string.

RParse ISO format dates
parse_date("2024-03-15") #> [1] "2024-03-15" parse_date(c("2024-03-15", "2024-12-01", "2025-01-31")) #> [1] "2024-03-15" "2024-12-01" "2025-01-31"

  

Non-ISO layouts need an explicit format. A day-first or month-first string returns NA unless you describe its order. The format string must match the separators in the data exactly.

RParse day-first and US-style dates
parse_date("15/03/2024", format = "%d/%m/%Y") #> [1] "2024-03-15" parse_date("03/15/2024", format = "%m/%d/%Y") #> [1] "2024-03-15"

  

Month names parse with %B and %b. Use %B for the full name and %b for the three-letter abbreviation. Literal text like the comma is written straight into the format string.

RParse dates written with month names
parse_date("March 15, 2024", format = "%B %d, %Y") #> [1] "2024-03-15" parse_date("15-Mar-24", format = "%d-%b-%y") #> [1] "2024-03-15"

  

A non-English locale unlocks foreign month names. Pass a locale() with a language code so %B matches names like mars or janvier. Without it, foreign names fail to parse.

RParse non-English month names
parse_date("15 mars 2024", format = "%d %B %Y", locale = locale("fr")) #> [1] "2024-03-15"

  

parse_date() vs as.Date() and lubridate

parse_date() reports failures; as.Date() can hide them. Base R's as.Date() does the same conversion but is quieter about bad values and uses a different default format. The lubridate helpers guess the order for you, which is convenient but less strict.

Function Format handling Bad values Best for
parse_date() Explicit format string NA plus a warning Importing columns predictably
as.Date() format argument, ISO default NA, often silent Quick one-off conversions
lubridate::dmy() Guesses from order helper NA plus a warning Messy mixed-format text
Tip
Reach for parse_date() inside data pipelines. Its warning when values fail to parse turns a silent data-quality bug into a visible one. For exploratory one-liners at the console, as.Date() or lubridate::ymd() are shorter.

Common pitfalls

Two-digit years guess the century. With %y, readr maps 00 to 68 into the 2000s and 69 to 99 into the 1900s. A value like "15-Mar-65" becomes 2065, not 1965.

RTwo-digit year century cutoff
parse_date("01-Jan-65", format = "%d-%b-%y") #> [1] "2065-01-01"

  

A missing format string silently produces all NA. If the data is not ISO 8601 and you forget format, every value fails. Always check for unexpected NA after parsing.

RNon-ISO text without a format fails
parse_date("03/15/2024") #> Warning: 1 parsing failure. #> [1] NA

  

Separators must match exactly. The format %d/%m/%Y will not parse "15-03-2024" because it expects slashes, not hyphens.

Try it yourself

Try it: Parse the character string "31 December 2023" into a Date object using the full month name. Save the result to ex_date.

RYour turn: parse a written date
# Try it: parse "31 December 2023" to a Date ex_date <- # your code here ex_date #> Expected: "2023-12-31"

  
Click to reveal solution
RSolution
ex_date <- parse_date("31 December 2023", format = "%d %B %Y") ex_date #> [1] "2023-12-31"

  

Explanation: %d matches the day, %B matches the full month name December, and %Y matches the four-digit year. The spaces in the format string match the spaces in the input.

These functions cover the rest of readr's value-parsing toolkit:

  • parse_datetime() parses a date together with a clock time into a POSIXct.
  • parse_time() parses clock times such as "14:30" into a time object.
  • parse_number() extracts numeric values from messy text.
  • col_date() applies a date format to a column inside read_csv().
  • read_csv() reads a delimited file and parses its columns in one step.

FAQ

What is the difference between parse_date() and as.Date()?

Both convert text to Date objects. parse_date() belongs to readr, warns loudly when values fail, and uses ISO 8601 as its no-format default. as.Date() is base R, often fails silently by returning NA, and defaults to the %Y-%m-%d format. Use parse_date() in data pipelines where you want failures surfaced, and as.Date() for quick console conversions.

Why does parse_date() return NA?

A value becomes NA when the text does not match the format string. The usual causes are a missing format argument on non-ISO data, separators that differ from the format, month names in a language the locale does not cover, or genuinely invalid dates like 2024-13-40. Run problems() on the result to see which rows failed and why.

What format codes does parse_date() use?

It uses strptime-style codes: %Y for a four-digit year, %y for a two-digit year, %m for the month number, %B for the full month name, %b for the abbreviated month name, and %d for the day of month. Any literal characters such as slashes, hyphens, or commas are written directly into the format string between the codes.

Can parse_date() handle a column with mixed date formats?

No. One call to parse_date() applies a single format string, so rows in a different layout return NA. For a column that mixes layouts, either clean it first, parse each format separately and combine the results, or use lubridate helpers that guess the order per value.

Conclusion

parse_date() is the dependable choice for date conversion. The readr parse_date() function turns date text into a real Date object in R. Supply a format string that matches your data, set a locale for non-English month names, and check for NA values that signal parse failures. For more on bringing external data into R, see the guide on importing data in R.

Prefer to learn by doing? Every track on the learning roadmap opens with a free section of interactive lessons, where you write the R yourself and the page tells you when it is wrong.