10: The System Clock

You can get the current time, either as a Unix timestamp (seconds since 1970) or as a broken-out structure of time elements (year, month, day, hour, minute, second).

The system clock is not guaranteed to line up with timer events (see section 4.4, "Timer Events"). Timer events may be delivered late according to the system clock.

void glk_current_time(glktimeval_t *time);

typedef struct glktimeval_struct {
    glsi32 high_sec;
    glui32 low_sec;
    glsi32 microsec;
} glktimeval_t;

The current Unix time is stored in the structure. (The argument may not be NULL.) This is the number of seconds since the beginning of 1970 (UTC).

The first two values in the structure should be considered a single signed 64-bit number. This allows the glktimeval_t to store a reasonable range of values in the future and past. The high_sec value will remain zero until sometime in 2106. If your computer is running in 1969, perhaps due to an unexpected solar flare, then high_sec will be negative.

The third value in the structure represents a fraction of a second, in microseconds (from 0 to 999999). The resolution of the glk_current_time() call is platform-dependent; the microsec value may not be updated continuously.

glsi32 glk_current_simple_time(glui32 factor);

If dealing with 64-bit values is awkward, you can also get the current time as a lower-resolution 32-bit value. This is simply the Unix time divided by the factor argument (which must not be zero). For example, if factor is 60, the result will be the number of minutes since 1970 (rounded towards negative infinity). If factor is 1, you will get the Unix time directly, but the value will be truncated starting some time in 2038.

10.1: Time and Date Conversions

void glk_time_to_date_utc(glktimeval_t *time, glkdate_t *date);
void glk_time_to_date_local(glktimeval_t *time, glkdate_t *date);

typedef struct glkdate_struct {
    glsi32 year;     /* full (four-digit) year */
    glsi32 month;    /* 1-12, 1 is January */
    glsi32 day;      /* 1-31 */
    glsi32 weekday;  /* 0-6, 0 is Sunday */
    glsi32 hour;     /* 0-23 */
    glsi32 minute;   /* 0-59 */
    glsi32 second;   /* 0-59, maybe 60 during a leap second */
    glsi32 microsec; /* 0-999999 */
} glkdate_t;

Convert the given timestamp (as returned by glk_current_time()) to a broken-out structure. The "utc" function returns a date and time in universal time (GMT); the "local" function returns local time.

[The seconds value may be 60 because of a leap second.]

void glk_simple_time_to_date_utc(glsi32 time, glui32 factor, glkdate_t *date);
void glk_simple_time_to_date_local(glsi32 time, glui32 factor, glkdate_t *date);

Convert the given timestamp (as returned by glk_current_simple_time()) to a broken-out structure in universal or local time. The time argument is multiplied by factor to produce a Unix timestamp.

Since the resolution of these functions is no better than seconds, they will return zero for the microseconds value.

void glk_date_to_time_utc(glkdate_t *date, glktimeval_t *time);
void glk_date_to_time_local(glkdate_t *date, glktimeval_t *time);

Convert the broken-out structure (interpreted as universal or local time) to a timestamp. The weekday value in glkdate_t is ignored. The other values need not be in their normal ranges; they will be normalized.

If the time cannot be represented by the platform's time library, this may return -1 for the seconds value. (I.e., the high_sec and low_sec fields both $FFFFFFFF. The microseconds field is undefined in this case.)

The glk_date_to_time_local() function may not be smart about Daylight Saving Time conversions. [If implemented with the mktime() libc function, it should use the negative tm_isdst flag to "attempt to divine whether summer time is in effect".]

glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);

Convert the broken-out structure (interpreted as universal or local time) to a timestamp divided by factor. The weekday value in glkdate_t is ignored. The other values need not be in their normal ranges; they will be normalized.

If the time cannot be represented by the platform's time library, this may return -1.

10.2: Testing for Clock Capabilities

Before calling Glk date and time functions, you should use the following gestalt selector.

res = glk_gestalt(gestalt_DateTime, 0);

This returns 1 if the overall suite of system clock functions, as described in this chapter, is available.

If this selector returns 0, you should not try to call these functions. They may have no effect, or they may cause a run-time error.

[Glk timer events are covered by a different selector. See section 4.4, "Timer Events").]

If you are writing a C program, you can perform a preprocessor test for the existence of GLK_MODULE_DATETIME. If this is defined, so are all the functions and data types described in this section.


Up to top Previous chapter Next chapter