|
| 1 | +# Time and duration |
| 2 | + |
| 3 | +Many services need to represent the concepts surrounding time. Representing |
| 4 | +time can be challenging due to the intricacies of calendars and time zones, as |
| 5 | +well as the fact that common exchange formats (such as JSON) lack a native |
| 6 | +concept of time. |
| 7 | + |
| 8 | +## Guidance |
| 9 | + |
| 10 | +Fields representing time **should** use a `string` field with values conforming |
| 11 | +to [RFC 3339][], such as `2012-04-21T15:00:00Z`. |
| 12 | + |
| 13 | +Services **should** use IDL-specific timestamps or format indicators where |
| 14 | +applicable (such as [`google.protobuf.Timestamp`][timestamp] in protocol |
| 15 | +buffers, or `format: date-time` in OpenAPI) provided that the service converts |
| 16 | +values to RFC 3339 timestamp strings in JSON. |
| 17 | + |
| 18 | +### Timestamps |
| 19 | + |
| 20 | +Fields that represent an absolute point in time (independent of any time zone |
| 21 | +or calendar) **should** use a `string` field with RFC 3339 values, and |
| 22 | +**should** send values in UTC, with the `Z` time zone explicitly included. |
| 23 | + |
| 24 | +These fields **should** have names ending in `_time`, such as `create_time` or |
| 25 | +`update_time`. For array fields, the names **should** end in `_times` instead. |
| 26 | + |
| 27 | +Many timestamp fields refer to an activity (for example, `create_time` refers |
| 28 | +to when the applicable resource was created). For these, the field **should** |
| 29 | +be named with the `{root_word}_time` form. For example, if a book is being |
| 30 | +published, the field storing the time when this happens would use the root form |
| 31 | +of the verb "to publish" ("publish"), resulting in a field called |
| 32 | +`publish_time`. Fields **should not** be named using the past tense (such as |
| 33 | +`published_time`, `created_time` or `last_updated_time`). |
| 34 | + |
| 35 | +When accepting timestamps as input, services **should** canonicalize the |
| 36 | +timestamp into UTC, and return values in UTC. |
| 37 | + |
| 38 | +### Durations |
| 39 | + |
| 40 | +Fields that represent a span between two points in time (independent of any |
| 41 | +time zone or calendar) **should** use an `int` field if there is a single |
| 42 | +canonical unit (for example, `ttl_seconds` for an expiring resource, or |
| 43 | +`offset_seconds` for position in a video). |
| 44 | + |
| 45 | +**Note:** A `float` field **may** be used if fractional seconds are needed. |
| 46 | +However, only fractional seconds are permitted; other fractional units (such as |
| 47 | +hours or days) **must not** be used. |
| 48 | + |
| 49 | +If there is no canonical unit, the service **should** use a `string` field with |
| 50 | +[ISO 8601][] duration values, such as `P3Y6M4DT12H30M5S`. The field name |
| 51 | +**should** end with `_duration`. Designators for zero values **may** be omitted |
| 52 | +in accordance with ISO 8601 (for example: `PT12H` is sufficient to represent |
| 53 | +"12 hours"), but at least one designator **must** be present (therefore, a zero |
| 54 | +duration is `PT0S` or `P0D`). |
| 55 | + |
| 56 | +Services **should** use IDL-specific durations where applicable (such as |
| 57 | +[`google.protobuf.Duration`][duration] in protocol buffers) provided that the |
| 58 | +service converts values to ISO 8601 duration strings in JSON. |
| 59 | + |
| 60 | +### Fractional seconds |
| 61 | + |
| 62 | +Services **may** support fractional seconds for both timestamps and durations, |
| 63 | +but **should not** support precision more granular than the nanosecond. |
| 64 | +Services **may** also limit the supported precision, and **may** _truncate_ |
| 65 | +values received from the user to the supported precision. |
| 66 | + |
| 67 | +**Note:** Truncation is recommended rather than rounding because rounding to |
| 68 | +the nearest second has the potential to change day, month, year, etc., which is |
| 69 | +surprisingly significant. |
| 70 | + |
| 71 | +### Civil dates and times |
| 72 | + |
| 73 | +Fields that represent a calendar date or wall-clock time **should** use partial |
| 74 | +ISO 8601 strings. |
| 75 | + |
| 76 | +Fields representing civil dates **should** have names ending in `_date`, while |
| 77 | +fields representing civil times or datetimes **should** have names ending in |
| 78 | +`_time`. |
| 79 | + |
| 80 | +### Recurring time |
| 81 | + |
| 82 | +A service that needs to document a recurring event **should** use cronspec if |
| 83 | +cronspec is able to support the service's use case. |
| 84 | + |
| 85 | +### Compatibility |
| 86 | + |
| 87 | +Occasionally, APIs are unable to use RFC 3339 strings for legacy or |
| 88 | +compatibility reasons. For example, an API may conform to a separate |
| 89 | +specification that mandates that timestamps be Unix timestamp integers. |
| 90 | + |
| 91 | +In these situations, fields **may** use other types. If possible, the following |
| 92 | +naming conventions apply: |
| 93 | + |
| 94 | +- Unix timestamps **should** use a `unix_time` suffix. |
| 95 | + - Multipliers of Unix time (such as milliseconds) **should not** be used; if |
| 96 | + they are unavoidable, the field name **should** use both `unix_time` and |
| 97 | + the unit, such as `unix_time_millis`. |
| 98 | +- For other integers, include the meaning (examples: `time`, `duration`, |
| 99 | + `delay`, `latency`) **and** the unit of measurement (valid values: `seconds`, |
| 100 | + `millis`, `micros`, `nanos`) as a final suffix. For example, |
| 101 | + `send_time_millis`. |
| 102 | +- For strings, include the meaning (examples: `time`, `duration`, `delay`, |
| 103 | + `latency`) but no unit suffix. |
| 104 | + |
| 105 | +In all cases, clearly document the expected format, and the rationale for its |
| 106 | +use. |
| 107 | + |
| 108 | +<!-- prettier-ignore-start --> |
| 109 | +[duration]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/duration.proto |
| 110 | +[iso 8601]: https://www.iso.org/iso-8601-date-and-time-format.html |
| 111 | +[rfc 3339]: https://datatracker.ietf.org/doc/html/rfc3339 |
| 112 | +[timestamp]: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto |
| 113 | +<!-- prettier-ignore-end --> |
0 commit comments