AIP-145

Ranges

Services often need to represent ranges of discrete or continuous values. These have wide differences in meaning, and come in many types: integers, floats, and timestamps, just to name a few, and the expected meaning of a range can vary in subtle ways depending on the type of range being discussed.

Guidance

A resource or message representing a range should ordinarily use two separate fields of the same type, with prefixes start_ and end_:

// A representation of a chapter in a book.
message Chapter {
  string title = 1;

  // The page where this chapter begins.
  int32 start_page = 2;

  // The page where the next chapter or section begins.
  int32 end_page = 3;
}

Inclusive or exclusive ranges

Fields representing ranges should use inclusive start values and exclusive end values (half-closed intervals) in most situations; in interval notation: [start_xxx, end_xxx).

Exclusive end values are preferable for the following reasons:

  • It conforms to user expectations, particularly for continuous values such as timestamps, and avoids the need to express imprecise "limit values" (e.g. 2012-04-20T23:59:59).
  • It is consistent with most common programming languages, including C++, Java, Python, and Go.
  • It is easier to reason about abutting ranges: [0, x), [x, y), [y, z), where values are chainable from one range to the next.

Timestamp intervals

The following section describes the use of the google.type.Interval type, found amongst the common protos that are described in AIP-213. This type represents a range between two timestamps, with an inclusive start value and exclusive end value.

Ranges between two timestamps which conform to the expectations of the Interval message should use this rather than having separate start and end fields. This allows client code to be written against the Interval message (such as checking whether a given timestamp occurs within the interval) and reused across multiple intervals in the same API, or even across multiple APIs.

APIs may use start and end timestamp fields instead. In particular, if a message within an API is inherently describing an interval with extra information about that interval, the additional level of nesting introduced by using the Interval message may be undesirable.

Exceptions

In some cases, there is significant colloquial precedent for inclusive start and end values (closed intervals), to the point that using an exclusive end value would be confusing even for people accustomed to them.

For example, when discussing dates (not to be confused with timestamps), most people use inclusive end: a conference with dates "April 21-23" is expected to run for three days: April 21, April 22, and April 23. This is also true for days of the week: a business that is open "Monday through Friday" is open, not closed, on Fridays.

In this situation, the prefixes first and last should be used instead:

// A representation of a chapter in a book.
message Chapter {
  string title = 1;

  // The first page of the chapter.
  int32 first_page = 2;

  // The last page of the chapter.
  int32 last_page = 3;
}

Fields representing ranges with significant colloquial precedent for inclusive start and end values should use inclusive end values with first_ and last_ prefixes for those ranges only. The service should still use exclusive end values for other ranges where this does not apply, and must clearly document each range as inclusive or exclusive.