Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/langdef.md
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,18 @@ Arithmetic operations raise an error when the results exceed the range of the
integer type (int, uint) or the timestamp or duration type. An error is also
raised for conversions which exceed the range of the target type.

There are a few additional considerations to keep in mind with respect to
how and when certain types will overflow:

* Duration values are limited to a single int64 value, or roughly +-290 years.
* Timestamp values are limited to the range of values which can be serialized
as a string: ["0001-01-01T00:00:00Z", "9999-12-31T23:59:59.999999999Z"].
* Double to int conversions are limited to (minInt, maxInt) non-inclusive.

Note, that whether the minimum or maximum integer value will roundtrip successfully
int -> double -> int can be compiler dependent which is the motivation for the
conservative round-tripping behavior.

### Timezones

Timezones are expressed in the following grammar:
Expand Down
28 changes: 23 additions & 5 deletions tests/simple/testdata/conversions.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,22 @@ section {
expr: "int(double(36028797018963969))"
value { int64_value: 36028797018963968 }
}
test {
name: "double_int_max_range"
description: "The double(2^63-1) cast produces a floating point value outside the int range"
expr: "int(9223372036854775807.0)"
eval_error {
errors: { message: "range" }
}
}
test {
name: "double_int_min_range"
description: "The double(-2^63) cast produces a floating point value outside the int range"
expr: "int(-9223372036854775808)"
eval_error {
errors: { message: "range" }
}
}
test {
name: "double_range"
expr: "int(1e99)"
Expand Down Expand Up @@ -469,13 +485,15 @@ section {
value { uint64_value: 36028797018963968 }
}
test {
name: "double_range_beyond_uint"
description: "Checks conversion of integer outside uint range."
expr: "uint(1e19)"
value: { uint64_value: 10000000000000000000 }
name: "double_uint_max_range"
description: "The exact conversion of uint max as a double does not round trip."
expr: "int(18446744073709551615.0)"
eval_error {
errors: { message: "range" }
}
}
test {
name: "double_range_err"
name: "double_range_beyond_uint"
expr: "uint(6.022e23)"
eval_error {
errors { message: "range" }
Expand Down
56 changes: 54 additions & 2 deletions tests/simple/testdata/timestamps.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,16 @@ section {
expr: "duration('600s') + duration('50s') == duration('650s')"
value: { bool_value: true }
}
test {
name: "add_time_to_duration_nanos_negative"
expr: "timestamp('0001-01-01T00:00:01.000000001Z') + duration('-999999999ns') == timestamp('0001-01-01T00:00:00.000000002Z')"
value: { bool_value: true }
}
test {
name: "add_time_to_duration_nanos_positive"
expr: "timestamp('0001-01-01T00:00:01.999999999Z') + duration('999999999ns') == timestamp('0001-01-01T00:00:02.999999998Z')"
value: { bool_value: true }
}
test {
name: "subtract_duration_from_time"
expr: "timestamp('2009-02-13T23:10:00Z') - duration('600s') == timestamp('2009-02-13T23:00:00Z')"
Expand Down Expand Up @@ -367,14 +377,42 @@ section {
}
test {
name: "add_duration_under"
expr: "timestamp('0001-01-01T00:00:00Z') - duration('10s')"
expr: "timestamp('0001-01-01T00:00:00Z') + duration('-1s')"
eval_error {
errors { message: "range" }
}
}
test {
name: "add_duration_over"
expr: "timestamp('9999-12-31T23:59:59Z') + duration('10s')"
expr: "timestamp('9999-12-31T23:59:59Z') + duration('1s')"
eval_error {
errors { message: "range" }
}
}
test {
name: "add_duration_nanos_over"
expr: "timestamp('9999-12-31T23:59:59.999999999Z') + duration('1ns')"
eval_error {
errors { message: "range" }
}
}
test {
name: "add_duration_nanos_under"
expr: "timestamp('0001-01-01T00:00:00Z') + duration('-1ns')"
eval_error {
errors { message: "range" }
}
}
test {
name: "sub_time_duration_over"
expr: "timestamp('9999-12-31T23:59:59Z') - timestamp('0001-01-01T00:00:00Z')"
eval_error {
errors { message: "range" }
}
}
test {
name: "sub_time_duration_under"
expr: "timestamp('0001-01-01T00:00:00Z') - timestamp('9999-12-31T23:59:59Z')"
eval_error {
errors { message: "range" }
}
Expand Down Expand Up @@ -411,4 +449,18 @@ section {
errors { message: "range" }
}
}
test {
name: "sub_under"
expr: "duration('-200000000000s') - duration('200000000000s')"
eval_error {
errors { message: "range" }
}
}
test {
name: "sub_over"
expr: "duration('200000000000s') - duration('-200000000000s')"
eval_error {
errors { message: "range" }
}
}
}