AIP-142
Time and duration
Many services need to represent the concepts surrounding time. Representing time can be challenging due to the intricacies of calendars and time zones, as well as the fact that common exchange formats (such as JSON) lack a native concept of time.
Guidance
Fields representing time should use the common, generally used components
(such as google.protobuf.Timestamp
or
google.type.Date
) for representing time or duration types. These
types are common components, and using them consistently allows
infrastructure and tooling to provide a better experience when interacting with
time values.
Timestamps
Fields that represent an absolute point in time (independent of any time zone
or calendar) should use the google.protobuf.Timestamp
type,
(which uses UNIX timestamps under the hood and hold nanosecond precision).
These fields should have names ending in _time
, such as create_time
or
update_time
. For repeated fields, the names should end in _times
instead.
Many timestamp fields refer to an activity (for example, create_time
refers
to when the applicable resource was created). For these, the field should
be named with the {imperative}_time
form. For example, if a book is being
published, the field storing the time when this happens would use the
imperative form of the verb "to publish" ("publish") resulting in a field
called publish_time
. Fields should not be named using the past tense
(such as published_time
, created_time
or last_updated_time
).
Durations
Fields that represent a span between two points in time (independent of any
time zone or calendar) should use the
google.protobuf.Duration
type.
To illustrate the distinction between timestamps and durations, consider a flight record:
// A representation of a (very incomplete) flight log.
message FlightRecord {
// The absolute point in time when the plane took off.
google.protobuf.Timestamp takeoff_time = 1;
// The length (duration) of the flight, from takeoff to landing.
google.protobuf.Duration flight_duration = 2;
}
Note: Observant readers may notice that the timestamp and duration
messages have the same structure (int64 seconds
and int32 nanos
). However,
the distinction between these is important, because they have different
semantic meaning. Additionally, tooling is able to base behavior off of which
message is used. For example, a Python-based tool could convert timestamps to
datetime objects and durations to timedelta
objects.
Relative time segments
In some cases, it may be necessary to represent a time segment inside a stream.
In these cases, the google.protobuf.Duration
type should be
used, and the field name should end with _offset
. To ensure that the
meaning is clear, the field must have a comment noting the point that the
offset is relative to.
To illustrate this, consider a resource representing a segment of an audio stream:
message AudioSegment {
// The duration relative to the start of the stream representing the
// beginning of the segment.
google.protobuf.Duration start_offset = 1;
// The total length of the segment.
google.protobuf.Duration segment_duration = 2;
}
Civil dates and times
Fields that represent a calendar date or wall-clock time should use the appropriate common components:
- Civil date:
google.type.Date
- Wall-clock time:
google.type.TimeOfDay
Fields representing civil dates should have names ending in _date
, while
fields representing civil times or datetimes should have names ending in
_time
.
Note: Both the Date
and TimeOfDay
components are timezone-naïve. Fields
that require timezone-awareness should use DateTime
(see below).
Civil timestamps
Fields that represent a civil timestamp (date and time, optionally with a time
zone) should use the google.type.DateTime
component, and the
field name should end in _time
.
Compatibility
Occasionally, APIs are unable to use the common structures for legacy or compatibility reasons. For example, an API may conform to a separate specification that mandates that timestamps be integers or ISO-8601 strings.
In these situations, fields may use other types. If possible, the following naming conventions apply:
- For integers, include the meaning (examples:
time
,duration
,delay
,latency
) and the unit of measurement (valid values:seconds
,millis
,micros
,nanos
) as a final suffix. For example,send_time_millis
. - For strings, include the meaning (examples:
time
,duration
,delay
,latency
) but no unit suffix.
In all cases, clearly document the expected format, and the rationale for its use.