Parsing dates and timestamps
to_date, to_timestamp and date_format patterns, and why yyyy and YYYY are not the same.
On this page
Show code in
Every code block on the page follows this.
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
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
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:
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
| Letter | Means | Example for 2024-12-30 09:05:07 |
|---|---|---|
| yyyy | Calendar year | 2024 |
| YYYY | Week-based year | 2025 (the week containing Dec 30 belongs to 2025) |
| MM | Month | 12 |
| mm | Minute | 05 |
| dd | Day of month | 30 |
| DD | Day of year | 365 |
| HH | Hour 0-23 | 09 |
| hh | Hour 1-12 (use with a) | 09 |
| ss | Second | 07 |
| EEE / EEEE | Day name | Mon / Monday |
| MMM | Month name | Dec |
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)andtimestamp_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 toUTCon every job so results do not depend on where the cluster runs. to_utc_timestampandfrom_utc_timestampconvert between UTC and a named zone such asAsia/Kolkata.
Common mistakes
YYYY instead of yyyy
mm instead of MM
Comparing date strings in dd/MM/yyyy form
Leaving the session time zone at the cluster default
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 questions1. 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.
- Label Late Shipments Easy
- Late Data in the Raw Zone Medium
- Files VACUUM Can Delete Medium
- Iceberg Hidden Partition Layout Medium
- Fill Missing Dates (Calendar Spine) Hard
Keep going
Up next · lesson 8 of 35 · 3 min readgroupBy + agg
Aggregate rows per group: counts, sums, averages, and how count(*) differs from count(col).
Related lessons
trunc / add_monthsPySpark functions · 3 min read
cast and schemasSpark internals · 4 min read
Watermarks and late data
Previous: String functions
Primary sources: Datetime patterns · functions.to_date · functions.date_format