Step 3 of 7
chrono durations
Passing time around as a bare int invites bugs. Is timeout = 30 seconds or milliseconds? Real outages have been caused by exactly that confusion. <chrono> puts the unit in the type, so the compiler keeps track and converts for you.
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
void wait_for(std::chrono::milliseconds t) {
std::cout << "waiting " << t.count() << " ms\n";
}
int main() {
wait_for(2s); // seconds convert to ms exactly
wait_for(250ms);
std::chrono::seconds lap = 95s;
auto m = std::chrono::duration_cast<std::chrono::minutes>(lap); // 1 (truncated)
auto rest = lap - m; // 35s
std::cout << m.count() << " min " << rest.count() << " s\n";
auto total = 1min + 30s + 500ms; // mixed units: the result is in ms
std::cout << total.count() << " ms\n";
std::cout << std::chrono::duration<double>(total).count() << " s\n";
}
waiting 2000 ms
waiting 250 ms
1 min 35 s
90500 ms
90.5 s
How it works
std::chrono::seconds,milliseconds,minutes,hoursand friends are all durations with a unit baked into the type. The literals2s,250ms,1mincome fromstd::chrono_literals.- Converting to a finer unit (seconds to milliseconds) is exact, so it happens implicitly, as in
wait_for(2s). - Converting to a coarser unit loses information (95 seconds isn't a whole number of minutes), so C++ makes you write
duration_cast, which truncates. - Adding different units gives the finer one automatically.
.count()returns the raw number in the duration's own unit. Use it only at the edges, for printing or talking to old APIs.std::chrono::duration<double>is seconds as a floating point number, handy for display.
Your task
Cast to std::chrono::minutes for the minutes. Then subtract those minutes from t and cast the remainder to std::chrono::seconds. Format with {}:{:02} so 7 seconds shows as 07.
Your turn: write std::string mmss(std::chrono::milliseconds t) that formats a round timer as M:SS (truncating the milliseconds), like 1:55 or 0:07.