When rain wiped out the first two sessions on the fifth day, the umpires ruled there would be a minimum of 53 overs played in the evening, which meant New Zealand would have to average 4.85 an over.
After a steady but slow start which saw the hosts at 90-3, Williamson and Daryl Mitchell picked up the pace.
They put on 142 in 26 overs for the fourth wicket with the precision of a one-day partnership.
Sri Lanka paid a heavy price for Williamson being dropped by Niroshan Dickwella on 33 as he went on to produce his 27th century.
The 31-year-old Mitchell, a late arrival on the international stage, contributed 81 to lift his average to a phenomenal 59.04 from 26 innings.
In a match of see-sawing fortunes, Sri Lanka had the upper hand on the opening two days before a first-innings century from Mitchell and a swashbuckling 72 from Matt Henry -- the last 60 from only 35 deliveries -- swung the game in New Zealand's favour.
Sri Lanka fought their way back into contention on the fourth day with a defiant 115 from Angelo Mathews, who built partnerships of 105 for the fifth wicket with Dinesh Chandimal and then 60 with Dhananjaya de Silva.
When the Sri Lanka second innings folded at 302 it left New Zealand needing 285 to win on a ground where the highest fourth-innings score was 256-8 by New Zealand in a 2018 draw against England.
Devon Conway was removed for five, leaving the outcome on a knife-edge going into the final day.
When play resumed on Monday, Prabath Jayasuriya made early in-roads with the wickets of Tom Latham for 25 and Henry Nicholls for 20.
Asitha Fernando bowled Mitchell and Tom Blundell (three) and had Michael Bracewell caught for 10 to leave New Zealand 266-6 and needing a further 19 runs with 16 balls left.
Williamson kept going to take the game to the final ball as Tim Southee (one) and Matt Henry (four) came and went, with Neil Wagner not out nought.
For Sri Lanka, Fernando took 3-63 and Jayasuriya 2-92.
The second Test starts in Wellington on Friday.