CodeRigor

FREE LESSON

Calendar time, CPU clocks & formatting

Distinguish time_t, tm and clock_t; format validated calendar fields and convert CPU ticks without assuming a Unix epoch or wall-clock timing.

The C time interfaces represent different things: time_t for simple calendar time, tm for broken-down fields and clock_t for processor time. Treating them as interchangeable integers creates portability bugs and misleading measurements.

Calendar fields have different offsets
The year and month are not the displayed numbers; day-of-month is already one-based.
Calendar fields have different offsets
The year and month are not the displayed numbers; day-of-month is already one-based.

Name the clock before interpreting its numbers

ISO C alone does not establish time_t as Unix seconds. POSIX adds stronger epoch and representation rules. Use difftime for differences between simple calendar times and a documented conversion for calendar fields. clock measures CPU time used by the program; its scale is CLOCKS_PER_SEC and its failure sentinel is clock_t(-1).

Waiting for a file or sleeping is not the same as consuming CPU. For elapsed wall-clock intervals in new C++, steady_clock expresses the monotonic requirement. The exercise uses synthetic CPU ticks so passing never depends on host scheduling or machine speed. Cast before arithmetic and division so fractional seconds are retained.

Follow one complete example

Run this program, then change one boundary while keeping the API preconditions valid. Predict its output before pressing Run.

C++
#include <cstdio>
#include <ctime>
int main() {
    std::tm fields{}; fields.tm_year=126; fields.tm_mon=9; fields.tm_mday=21;
    char output[32]{};
    if(std::strftime(output,sizeof output,"%Y-%m-%dT%H:%M:%S",&fields)==0)return 1;
    std::printf("%s\n",output);
    auto ticks=std::clock_t(CLOCKS_PER_SEC/2);
    std::printf("CPU interval: %.3f seconds\n",double(ticks)/CLOCKS_PER_SEC);
}
Validate, format privately, then publish
The output remains unchanged when validation or formatting fails.
Validate, format privately, then publish
The output remains unchanged when validation or formatting fails.

Understand the calendar field conventions

tm_year is years since 1900 and tm_mon is zero-based; tm_mday starts at one. Our formatter validates actual Gregorian dates rather than using mktime to normalize mistakes. Century leap-year rules matter: 2000 has February 29, while 1900 and 2100 do not. Its bounded teaching policy allows years 1900–9999 and excludes leap seconds.

mktime interprets local time, including daylight-saving rules; it is not a timezone-free UTC converter. gmtime and localtime can return nullptr and may share static storage. Copy a successful result promptly when a lasting snapshot is needed, and use a suitable concurrency policy. POSIX _r variants and platform-specific alternatives are separate contracts, not extra guarantees of the ISO C baseline.

Choose by the time question
A CPU interval, a wall-clock duration and a calendar date need different interfaces.
Choose by the time question
A CPU interval, a wall-clock duration and a calendar date need different interfaces.

Formatting does not assign a timezone

strftime formats fields under the active locale. The exercise uses a numeric pattern and a stable C locale to make the result predictable. The input tm contains calendar fields without an explicit timezone assertion, so output does not gain a Z suffix merely because the text resembles ISO date/time notation.

A zero strftime result does not provide a complete usable output string. Format into a private temporary, require the expected length, then copy the text and NUL to the caller. Validate capacity and fields first so failure changes nothing. Keep locale, timezone and calendar validation as explicit policies rather than silently deriving them from the buffer size.

Read the return value

Predict this smaller case. The check item later changes the values, so explain the rule as well as the output.

C++
#include <cstdio>
#include <ctime>
int main(){std::tm t{};t.tm_year=125;t.tm_mon=0;t.tm_mday=2;char b[16];if(!std::strftime(b,sizeof b,"%Y-%m-%d",&t))return 1;std::printf("%s %.1f\n",b,double(CLOCKS_PER_SEC)/CLOCKS_PER_SEC);}

Complete the faded example

State the missing precondition or result check before filling the code. The fill exercise supplies the rest of the implementation.

C++
if (begin==std::clock_t(-1) || end==std::clock_t(-1) || end<begin) return std::nullopt;
// Fill: return fractional CPU seconds without integer division.
// Do not label this value elapsed wall-clock time.

Check your model

If a program sleeps for two seconds, why is requiring clock() to advance by exactly two CPU seconds an invalid test?

Practice the boundary

Implement format_calendar(std::tm, std::span<char>) -> bool and cpu_seconds(std::clock_t begin, std::clock_t end) -> std::optional<double>.

The caller holds LC_TIME at "C". Calendar formatting accepts actual Gregorian dates from 1900 through 9999, with hours 0–23, minutes/seconds 0–59. tm_year is years since 1900; tm_mon is 0–11. Ignore tm_wday, tm_yday and tm_isdst because this numeric format does not use them. Reject invalid dates rather than normalizing them. Leap seconds are outside this teaching API.

Write exactly YYYY-MM-DDTHH:MM:SS plus NUL using strftime. It describes the supplied calendar fields, without asserting a timezone or adding Z. Require capacity >=20. On any failure return false and leave output unchanged; use a private temporary for the strftime call, whose contents are not usable on a zero result. Bytes beyond those 20 stay unchanged.

cpu_seconds returns the difference in CPU seconds using CLOCKS_PER_SEC. Reject either clock failure sentinel (-1), and end < begin (wrap/reversed input). The input interval has no other wrap. Convert before subtraction/division to avoid integer truncation/overflow. This is CPU time, not a monotonic wall-clock stopwatch; tests use synthetic ticks, never speed thresholds.

Read → six checks → two bug hunts → fill → build. A successful graded submission is evidence; reading or watching alone does not grant mastery. Review cards reinforce API choices separately.

Watch and verify

The Watch & read panel links a free lecture for the relevant background and primary API references. The lecture notes say which parts are background; the tested contract here supplies the exact wrapper policy.

C standard-library course · C library review cards · Unix/Linux systems

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Compare clocks, durations and time points with the C interfaces here. This is a chrono talk for context, not a demonstration of the C calendar-formatting API.