Advanced

Dates and time zones

Dates sort wrong, group wrong, and diff wrong when they are strings. Parse them into real date objects once, and the comparisons become correct. Time zones are the second trap, and they are the one that bites across a whole team.

What you will see

2026-01-15, 2026-04-03, 2026-11-02 - ISO with padding sorts correctly, which is why the format is the standard.

About 1 min of reading

Try It

Sort dates correctly and derive a month key.

1

Show the string sort trap

print(sorted(['2026-04-03','2026-11-02','2026-1-15']))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
The '2026-1-15' entry sorts last because '1' < '4' as text - a single digit month breaks the sort.
2

Fix it with zero padding

print(sorted(['2026-04-03','2026-11-02','2026-01-15']))

Before you run it, say out loud what it will print. Then open the answer.

What it prints
2026-01-15, 2026-04-03, 2026-11-02 - ISO with padding sorts correctly, which is why the format is the standard.

Data Flow

Text becomes a date, then a period key.
1 Parse the string into a date value
↓
2 Normalise to one zone
↓
3 Derive the period key
↓
4 Group by the key
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

print(sorted(['2026-04-03','2026-11-02','2026-1-15'])) The '2026-1-15' entry sorts last because '1' < '4' as text - a single digit month breaks the sort.
Why this works
Ambiguous formats

03/04/2026 is the third of April or the fourth of March. Nothing in the string resolves it. Standardise on ISO 8601 (2026-04-03) at the boundary where the data is produced, and record which format was assumed if you cannot.

Boundaries of a period

'This month' means different things at the start and end of a month, and a period that crosses a DST change is not a whole number of hours. Use period boundaries computed from dates, not hour counts.

Examples

Parse, do not compare

datetime.strptime(s, '%Y-%m-%d') or new Date(...) turns text into a value with real ordering. Sorting ISO 8601 strings happens to work, and that coincidence is why people leave them as strings. It fails the moment the format varies.

Store UTC, display local

Keep one representation internally, UTC, and convert only at display time. Mixing local and UTC in the same column produces timestamps that are individually valid and collectively wrong.

Group by a derived period

Ask for the month or the week, not the day, by deriving the key from the date: r['2026-10'] or an ISO week. Grouping on the raw timestamp gives one group per timestamp and a table nobody can read.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Loops versus vectorised work
Previous Lesson
Loops versus vectorised work
Next Lesson
Outliers and what a mean hides
Outliers and what a mean hides →