Skip to content
Everyone knows 3 min read · Dates 8 practice problems ↓

Parsing dates and timestamps

to_date, to_timestamp and date_format patterns, and why yyyy and YYYY are not the same.

You will learn

  • How to turn strings into dates and timestamps with to_date and to_timestamp
  • How datetime patterns work, and the yyyy vs YYYY trap
  • How to format dates for reports with date_format
  • How time zones affect timestamps

Read first

Comfortable with these? Read on.

TL;DR F.to_date(col, "dd/MM/yyyy") parses a string with a pattern; without a pattern it expects yyyy-MM-dd. A string that does not match becomes null. In patterns, yyyy is the calendar year and MM the month, while YYYY is a week-based year and mm is minutes.

Dates, timestamps and strings

A DATE is a calendar day. A TIMESTAMP is an instant in time, shown in the session time zone. Strings that look like dates are just text: they sort correctly only in yyyy-MM-dd form, and you cannot add days to them. Parse once, early, and keep real date types.

Run the example

PySparkSpark SQL
from pyspark.sql import functions as F
result = signups.select(
    "user",
    F.to_date("signup_raw", "dd/MM/yyyy").alias("signup_date"),
    F.to_timestamp("last_login").alias("login_ts"),
    F.date_format(F.to_timestamp("last_login"), "EEE HH:mm").alias("login_label"),
    F.datediff(F.to_date("last_login"), F.to_date("signup_raw", "dd/MM/yyyy")).alias("days_to_login"),
)
SELECT user,
       to_date(signup_raw, 'dd/MM/yyyy')        AS signup_date,
       to_timestamp(last_login)                 AS login_ts,
       date_format(last_login, 'EEE HH:mm')     AS login_label,
       datediff(to_date(last_login), to_date(signup_raw, 'dd/MM/yyyy')) AS days_to_login
FROM signups

Switch to PySpark to edit and run this example in your browser.

Cy's signup is null: 2025-02-20 does not match dd/MM/yyyy. Di has no login, so everything computed from it is null.

Mixed formats in one column

Try each format in turn and take the first that parses. coalesce returns the first non-null:

PySparkSpark SQL · Several formats
signup_date = F.coalesce(
    F.to_date("signup_raw", "dd/MM/yyyy"),
    F.to_date("signup_raw", "yyyy-MM-dd"),
)
coalesce(to_date(signup_raw, 'dd/MM/yyyy'), to_date(signup_raw, 'yyyy-MM-dd'))

In Spark 4.0 with ANSI mode on, to_date raises an error for a string that does not match; use try_to_timestamp or try_to_date style functions where available, or set the pattern per source so mismatches cannot happen.

Pattern letters

LetterMeansExample for 2024-12-30 09:05:07
yyyyCalendar year2024
YYYYWeek-based year2025 (the week containing Dec 30 belongs to 2025)
MMMonth12
mmMinute05
ddDay of month30
DDDay of year365
HHHour 0-2309
hhHour 1-12 (use with a)09
ssSecond07
EEE / EEEEDay nameMon / Monday
MMMMonth nameDec
Watch out: YYYY-MM-dd looks right and works for most of the year, then prints 2025-12-30 for 30 December 2024. It is a classic bug that only appears in the last days of December. Always use lower-case yyyy.

Formatting for output

date_format(col, pattern) turns a date or timestamp into a string. Keep it for the last step (reports, file names, labels): once formatted, the column is text again. To group by month, prefer trunc(col, "month"), which stays a date and sorts correctly.

Epoch seconds and time zones

  • unix_timestamp(col) returns seconds since 1970-01-01 UTC; from_unixtime(secs) and timestamp_seconds(secs) go back.
  • Epoch milliseconds (common in Kafka and APIs) need dividing by 1000 first, or use timestamp_millis.
  • Parsing a timestamp string with no offset interprets it in spark.sql.session.timeZone. Set it to UTC on every job so results do not depend on where the cluster runs.
  • to_utc_timestamp and from_utc_timestamp convert between UTC and a named zone such as Asia/Kolkata.

Common mistakes

YYYY instead of yyyy

Week-based year: wrong for a few days around New Year.

mm instead of MM

Minutes instead of months.

Comparing date strings in dd/MM/yyyy form

"02/01/2025" sorts after "01/12/2025". Parse first.

Leaving the session time zone at the cluster default

The same job gives different timestamps in different regions. Set it to UTC.

Key takeaways

  • to_date and to_timestamp parse strings; mismatches become null (or errors under ANSI).
  • yyyy is the year, YYYY is the week-based year; MM is month, mm is minute.
  • Use coalesce over several to_date calls for mixed formats.
  • Format with date_format only at the end; set the session time zone to UTC.

Check yourself

3 questions

1. What does to_date("2025-02-20", "dd/MM/yyyy") return in classic Spark?

Show the answer

null. The string does not match the pattern, so the result is null.

2. Which pattern prints the calendar year?

Show the answer

yyyy. Lower-case yyyy is the year; upper-case YYYY is the week-based year.

3. What does "mm" mean in a pattern?

Show the answer

Minute. MM is month; mm is minute.

Practice it

Interview problems that use this: write the PySpark, run it, and get graded on hidden tests.

Solve: Label Late Shipments →
See all 8 problems →

Keep going

Up next · lesson 8 of 35 · 3 min read
groupBy + agg
Aggregate rows per group: counts, sums, averages, and how count(*) differs from count(col).

Related lessons

Previous: String functions

Primary sources: Datetime patterns · functions.to_date · functions.date_format