Skip to content

Date and time (time.h)

Include time.h for calendar types, clock access, broken-down time conversion, and fixed-C-locale formatting.

Types and Macros

Name Meaning
clock_t Processor time type; same width as long on this target.
time_t Signed 32-bit calendar time type; same representation as long.
CLOCKS_PER_SEC clock() ticks per second. CP/M 2.2 has no clock; clock() returns -1.
struct tm Broken-down calendar time.

struct tm contains the standard C89 fields. DCC uses 16-bit int members, 32-bit time_t and clock_t, and no timezone extension fields.

Functions

Function Summary
char *asctime(const struct tm *tp) Convert *tp to a string of the form "Www Mmm dd hh:mm:ss yyyy\n" in an internal 26-byte static buffer (not reentrant). Returns NULL without modifying that buffer if tp is NULL, weekday/month is out of range, any numeric clock/date field is outside its struct tm range, or the actual year is outside 0000..9999.
clock_t clock(void) Processor time used since program start; returns (clock_t)-1 (unavailable on CP/M 2.2).
char *ctime(const time_t *tp) Equivalent to asctime(localtime(tp)). Returns NULL if tp is NULL.
float difftime(time_t t1, time_t t0) Difference t1-t0 as a floating-point count of seconds. The subtraction is evaluated without signed-long overflow before rounding the mathematical result to the target's single-precision float. Note: C89 returns double; dcc returns float (no double type).
struct tm *gmtime(const time_t *tp) Convert tp to broken-down time in an internal static buffer (not reentrant). Returns NULL if tp is NULL or tp is negative; time_t bit patterns 0x80000000 through 0xffffffff are therefore rejected.
struct tm *localtime(const time_t *tp) Identical to gmtime(tp): this target has no timezone database, so the BDOS clock's raw reading already is "local" time, with no UTC offset to apply (see time()'s own comment above).
time_t mktime(struct tm *tp) Convert broken-down time tp (year/mon/mday/hour/min/sec) to a time_t, and normalize tp in place. All six input fields may be out of range and are combined before the representability check, so e.g. 1969-12-32 becomes 1970-01-01. tm_wday/tm_yday are always recomputed. Returns (time_t)-1 and leaves *tp byte-for-byte unchanged for NULL, a normalized pre-1970 value, or any value after the signed 32-bit maximum (including 2106-era unsigned bit patterns and values that would wrap modulo 2^32). It does not modify the shared object previously returned by gmtime/localtime when tp points to an unrelated object.
size_t strftime(char *s, size_t max, const char *fmt, const struct tm *tp) Format broken-down time in the fixed C locale.
time_t time(time_t *tp) Current calendar time; stores through tp if non-null. Reads a real clock via BDOS function 105 (CP/M 3+ "Get Date and Time") when the underlying system/emulator implements it - many do even while still reporting CP/M 2.2 via BDOS 12. The result tracks the BDOS clock's raw wall-clock reading with no timezone adjustment (CP/M has no timezone concept), encoded as a Unix time_t. Returns (time_t)-1, and stores -1 through tp, when the underlying BDOS doesn't actually implement the call (e.g. real CP/M 2.2 hardware), supplies invalid packed BCD, or reports a value after 2038-01-19 03:14:07. CP/M day 1 is 1978-01-01; the runtime's conversion therefore maps CP/M day 0 to Unix day 2921 (1977-12-31).

Clock and calendar model

clock() returns (clock_t)-1: CP/M 2.2 has no processor-time service. time() reads BDOS function 105 when the system or emulator implements it and otherwise returns (time_t)-1. The result is the BDOS wall-clock reading encoded as a signed Unix timestamp.

This is an epoch-based encoding of the BDOS clock fields, not a guarantee that the clock is set to UTC. There is no timezone correction. The checked upper limit is 2038-01-19 03:14:07; later timestamps or invalid clock fields return (time_t)-1. If a non-NULL output pointer is supplied to time, the result, including the failure value, is stored there too.

There is no timezone database. localtime() is therefore identical to gmtime(), and %Z in strftime() expands to an empty string. asctime() and the broken-down-time conversion functions use internal static storage. A later gmtime() or localtime() call replaces their shared result, but mktime() on an unrelated struct tm does not.

Fixed-C-locale strftime

strftime() supports every C89 conversion available from struct tm, plus the %C century extension:

Conversion Fixed C-locale result
%a, %A abbreviated or full weekday name
%b, %B abbreviated or full month name
%C calendar century (year / 100), at least two digits
%c Www Mmm dd hh:mm:ss yyyy (space-padded one-digit day)
%d, %H, %I, %j, %m, %M, %S zero-padded numeric fields
%p AM or PM
%U, %W Sunday-first or Monday-first week number
%w weekday number, Sunday is zero
%x mm/dd/yy
%X hh:mm:ss
%y, %Y two-digit or full year
%Z empty string
%% literal percent sign

The locale is always "C"; no locale data is linked. tm_isdst is ignored, and fields are not normalized or cross-checked against each other.

max == 0 returns zero without accessing any pointer. For a positive bound, all pointers must be non-NULL and the range-bearing struct tm fields must be valid. An unknown conversion or trailing % is rejected. Invalid input or an insufficient destination returns zero and leaves the longest fitting prefix NUL-terminated; a successful empty result also returns zero.