Title

POSIX Timespecs

Author

John Cowan <cowan@ccil.org>

Status

This SRFI is currently in final status. Here is an explanation of each status that a SRFI can hold. To provide input on this SRFI, please send email to srfi-174@nospamsrfi.schemers.org. To subscribe to the list, follow these instructions. You can access previous messages via the mailing list archive.

Abstract

This SRFI defines the trivial type timespec, which is used to represent the struct timespec defined by the POSIX <time.h> header.

Rationale

The reason for putting this very simple and straightforward type into a SRFI (and library) of its own is that timespecs are part of the interface for more than one SRFI. If they are defined in just one SRFI and imported by the rest, that produces an otherwise useless and unnecessary dependency on the SRFI containing the definition. This arises particularly in R6RS and R7RS because record types are generative (distinct definitions lead to distinct record types) and because most implementations report a warning or even an error if the same identifier is imported from more than one library, unless they have both imported it in turn from the same original library.

Specification

Timespec is an immutable type that holds two exact integer values:

It is recommended, but not absolutely required, that timespecs be a disjoint and immutable type. For efficiency's sake they may be represented otherwise in particular implementations. If they are not disjoint, the exact representation (such as a SRFI 19 time object or a pair) must be documented by the implementation.

If timespecs are represented as SRFI 19 time objects, the timespec constructor must set the SRFI 19 time type to TIME_UTC. It is an error to mutate a time object (or pair, or other type) that is serving as a timespec, and if this is done, code relying on the immutability of timespecs will break.

Note that IEEE 64-bit floats are not a sufficient representation for timespecs,

It is recommended, but not required, that timespecs be a disjoint type, but for efficiency's sake they may be represented otherwise in particular implementations. It is an error to mutate the values held in a timespec object. Note that IEEE 64-bit floats are not a sufficient representation, because their nanosecond-precision range is confined to a period of 208 days centered on the epoch.

In no case can this SRFI guarantee anything about the accuracy of timespecs, or the precision of any timespec sources. Since it is difficult to usefully determine and communicate timestamp precision and accuracy in most applications, the timespec type does not contain any standard field to hold such information.

Documentation requirements

An implementation of this SRFI must document:

Procedures

(timespec seconds nanoseconds)

Returns a timespec with the given seconds and nanoseconds components.

(timespec? obj)

Returns #f if obj is definitely not a timespec, and #t if it is most probably one.

If timespecs are a disjoint type, this procedure simply tests whether obj belongs to that type. If not, then each component is checked to see if it is an exact integer, and in the case of the nanoseconds component, whether it is a non-negative integer less than 109. In addition, if the implementation knows that its fixnum width is at least 40 bits, it can also check that the value of the seconds component is a fixnum.

(timespec-seconds timespec)

Returns the seconds component of timespec. The result must be the same (in the sense of eqv?) as the value passed to timespec.

(timespec-nanoseconds timespec)

Returns the nanoseconds component of timespec. The result must be the same (in the sense of eqv?) as the value passed to timespec.

(inexact->timespec inexact)

Converts inexact into an approximate number of seconds and nanoseconds since the (unspecified) epoch and returns the results as a timespec object.

(timespec->inexact timespec)

Returns an inexact number representing the seconds from the epoch to the value of timespec.

Note that these operations are not inverses, because inexact numbers typically do not have nanosecond precision.

(timespec=? timespec1 timespec2)

Returns #t if timespec1 and timespec2 represent the same instant of time, and #f otherwise.

(timespec<? timespec1 timespec2)

Returns #t if timespec1 represents an earlier instant of time than timespec2, and #f otherwise.

Note that it is an (undetectable) error to compare two timespecs that are relative to different epochs.

(timespec-hash timespec)

Returns an exact non-negative integer representing a hash code for timespec.

Implementation

An implementation of SRFI 174 is in the repository of this SRFI. The files are:

Note: A pair-based implementation is also available; simply comment out the `define-record-type` declaration in srfi/174.sld and remove the comment markers from the declarations that follow.

Acknowledgements

Discussions between me, Lassi Kortela, and Harold Ancell, mostly on the SRFI 170 mailing list, made the need for this SRFI clear.

Copyright

Copyright © John Cowan (2019).

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Editor: Arthur A. Gleckler