Skip to content
AZ Tools

Calendar Heatmap from Date List

Paste a list of YYYY-MM-DD dates (with optional counts) and render a GitHub-style yearly heatmap — palette, week start, streaks, hover counts.

How to use

  1. Paste your dates, one per line. Optional second column is the count (default 1) — duplicates on the same date are summed.
  2. Set the year and choose a palette + week start. Hover any cell to see its date and count.
  3. Read the streak metrics below: total active days, average per active day, longest and current streaks.

About this tool

Show

Turns a column of dates into the GitHub-contribution-graph view of a year. Each line can be just a date (2026-03-15) for count 1, or a date with a number (2026-03-15 4) when you have weights. The grid auto-bins counts into five intensity levels relative to the year's peak, picks a palette, and surfaces the longest streak and current streak below. Useful for habit trackers, commit history copies, sales/error logs — any time-series where the rhythm matters more than the exact value.

Binning relative to the year's peak is what makes the picture readable and also what makes two charts incomparable. A single outlier day compresses everything else into the palest band, so a year with one enormous spike looks emptier than a steady year with a lower total. Two heatmaps side by side are showing different scales unless you say otherwise, and reading one against the other is the mistake the format invites.

The five levels mean the colour is an ordering rather than a quantity. You can see that Tuesdays are busier than Thursdays and that a habit lapsed in August; you cannot read a value off a square, and a step from one shade to the next is not a fixed number of units. That is the trade the format makes, and it is the right one when the question is about rhythm.

Streaks are counted in calendar days with no notion of a rest day, so a habit deliberately done five days a week shows a longest streak of five however consistent it is. A missing line is a zero rather than missing data, which matters when the source stops logging: a broken exporter and a genuinely idle month look identical here.

The grid is laid out in weeks, and which day the column starts on shifts the whole pattern. If you are comparing against a chart drawn elsewhere, check that both start the week the same way before reading anything into the shape.

Frequently asked questions

What format do dates need to be in?

ISO YYYY-MM-DD at the start of the line. Anything after the date is treated as a count (must be numeric). Lines starting with # are comments and skipped.

How are intensity levels assigned?

Five bins relative to the year's peak — empty, <25%, <50%, <75%, ≥75%. So a day at 50% of your busiest day uses the middle shade. The bins re-balance whenever the data changes.

Why does one huge day flatten the rest of my year?

Because the five intensity levels are scaled to the year's peak, so a single outlier pushes every ordinary day into the lightest band. If one day is genuinely exceptional, either cap it at a sensible ceiling before pasting, or split that day's count across the entries it represents. A heatmap is a comparison of typical days, and one spike destroys that comparison.

The streak count looks wrong. What is it measuring?

Consecutive calendar days that appear in your list, with no allowance for weekends or holidays. A habit tracked only on weekdays therefore shows a maximum streak of five, and a missing day breaks the run even if nothing was expected that day. If weekdays are what you care about, remove the weekend gaps from the question rather than reading the streak as a failure.

Related tools