This page provides an overview of all GoogleSQL for SecOps data types, including information about their value domains. For information on data type literals and constructors, see Lexical Structure and Syntax.
Data type list
| Name | Summary |
|---|---|
| Array type |
An ordered list of zero or more elements of non-array values. SQL type name: ARRAY
|
| Boolean type |
A value that can be either TRUE or FALSE.SQL type name: BOOLSQL aliases: BOOLEAN
|
| Bytes type |
Variable-length binary data. SQL type name: BYTES
|
| Date type |
A Gregorian calendar date, independent of time zone. SQL type name: DATE
|
| Datetime type |
A Gregorian date and a time, as they might be displayed on a watch,
independent of time zone. SQL type name: DATETIME
|
| Numeric types |
A numeric value. Several types are supported.
A 64-bit integer.
A decimal value with precision of 38 digits.
An approximate double precision numeric value. |
| String type |
Variable-length character data. SQL type name: STRING
|
| Struct type |
Container of ordered fields. SQL type name: STRUCT
|
| Time type |
A time of day, as might be displayed on a clock, independent of a specific
date and time zone. SQL type name: TIME
|
| Timestamp type |
A timestamp value represents an absolute point in time,
independent of any time zone or convention such as
daylight saving time (DST). SQL type name: TIMESTAMP
|
Data type properties
When storing and querying data, it's helpful to keep the following data type properties in mind:
Nullable data types
For nullable data types, NULL is a valid value. Currently, all existing
data types are nullable. Conditions apply for
arrays.
Orderable data types
Expressions of orderable data types can be used in an ORDER BY clause.
Applies to all data types except for:
ARRAYSTRUCT
Ordering NULLs
In the context of the ORDER BY clause, NULLs are the minimum
possible value; that is, NULLs appear first in ASC sorts and last in
DESC sorts.
NULL values can be specified as the first or last values for a column
irrespective of ASC or DESC by using the NULLS FIRST or NULLS LAST
modifiers respectively.
To learn more about using ASC, DESC, NULLS FIRST and NULLS LAST, see
the ORDER BY clause.
Ordering floating points
Floating point values are sorted in this order, from least to greatest:
NULLNaN— AllNaNvalues are considered equal when sorting.-inf- Negative numbers
- 0 or -0 — All zero values are considered equal when sorting.
- Positive numbers
+inf
Groupable data types
Groupable data types can generally appear in an expression following GROUP BY,
DISTINCT, and PARTITION BY. All data types are supported except for:
Grouping with floating point types
Groupable floating point types can appear in an expression following GROUP BY
and DISTINCT. PARTITION BY expressions can't
include floating point types.
Special floating point values are grouped in the following way, including
both grouping done by a GROUP BY clause and grouping done by the
DISTINCT keyword:
NULLNaN— AllNaNvalues are considered equal when grouping.-inf- 0 or -0 — All zero values are considered equal when grouping.
+inf
Grouping with arrays
An ARRAY type is groupable if its element type is
groupable.
Two arrays are in the same group if and only if one of the following statements is true:
- The two arrays are both
NULL. - The two arrays have the same number of elements and all corresponding elements are in the same groups.
Grouping with structs
A STRUCT type is groupable if its field types are
groupable.
Two structs are in the same group if and only if one of the following statements is true:
- The two structs are both
NULL. - All corresponding field values between the structs are in the same groups.
Comparable data types
Values of the same comparable data type can be compared to each other. All data types are supported except for:
ARRAY
Notes:
- Equality comparisons for structs are supported field by field, in field order. Field names are ignored. Less than and greater than comparisons aren't supported.
- All types that support comparisons can be used in a
JOINcondition. See JOIN Types for an explanation of join conditions.
Array type
| Name | Description |
|---|---|
ARRAY |
Ordered list of zero or more elements of any non-array type. |
An array is an ordered list of zero or more elements of non-array values. Elements in an array must share the same type.
Arrays of arrays aren't allowed. Queries that would produce an array of arrays return an error. Instead, a struct must be inserted between the arrays.
To learn more about the literal representation of an array type, see Array literals.
To learn more about using arrays in GoogleSQL, see Work with arrays.
NULLs and the array type
Currently, GoogleSQL for SecOps has the following rules with respect to NULLs and
arrays:
An array can be
NULL.For example:
SELECT CAST(NULL AS ARRAY<INT64>) IS NULL AS array_is_null; /*---------------+ | array_is_null | +---------------+ | TRUE | +---------------*/A struct can't contain a
NULLarray.For example, this raises an error:
-- error SELECT STRUCT(CAST(NULL AS ARRAY<INT64>) AS numbers) AS items;An empty array and a
NULLarray are two distinct values inside a query.For example:
WITH Items AS ( SELECT [] AS numbers UNION ALL SELECT CAST(NULL AS ARRAY<INT64>)) SELECT numbers FROM Items; /*---------+ | numbers | +---------+ | [] | | NULL | +---------*/GoogleSQL for SecOps raises an error if the query result has an array which contains
NULLelements.For example, these raise an error:
-- error SELECT FORMAT("%T", [1, NULL, 3]) as numbers;-- error SELECT [1, NULL, 3] as numbers;
Declaring an array type
ARRAY<T>
Array types are declared using the angle brackets (< and >). The type
of the elements of an array can be arbitrarily complex with the exception that
an array can't directly contain another array.
Examples
| Type Declaration | Meaning |
|---|---|
ARRAY<INT64>
|
Simple array of 64-bit integers. |
ARRAY<STRUCT<INT64, INT64>>
|
An array of structs, each of which contains two 64-bit integers. |
ARRAY<ARRAY<INT64>>
(not supported) |
This is an invalid type declaration which is included here just in case you came looking for how to create a multi-level array. Arrays can't contain arrays directly. Instead see the next example. |
ARRAY<STRUCT<ARRAY<INT64>>>
|
An array of arrays of 64-bit integers. Notice that there is a struct between the two arrays because arrays can't hold other arrays directly. |
Constructing an array
You can construct an array using array literals or array functions.
Using array literals
You can build an array literal in GoogleSQL using brackets ([ and
]). Each element in an array is separated by a comma.
SELECT [1, 2, 3] AS numbers;
SELECT ["apple", "pear", "orange"] AS fruit;
SELECT [true, false, true] AS booleans;
You can also create arrays from any expressions that have compatible types. For example:
SELECT [a, b, c]
FROM
(SELECT 5 AS a,
37 AS b,
406 AS c);
SELECT [a, b, c]
FROM
(SELECT CAST(5 AS INT64) AS a,
CAST(37 AS FLOAT64) AS b,
406 AS c);
Notice that the second example contains three expressions: one that returns an
INT64, one that returns a FLOAT64, and one that
declares a literal. This expression works because all three expressions share
FLOAT64 as a supertype.
To declare a specific data type for an array, use angle
brackets (< and >). For example:
SELECT ARRAY<FLOAT64>[1, 2, 3] AS floats;
Arrays of most data types, such as INT64 or STRING, don't require
that you declare them first.
SELECT [1, 2, 3] AS numbers;
You can write an empty array of a specific type using ARRAY<type>[]. You can
also write an untyped empty array using [], in which case GoogleSQL
attempts to infer the array type from the surrounding context. If
GoogleSQL can't infer a type, the default type ARRAY<INT64> is used.
Using generated values
You can also construct an ARRAY with generated values.
Generating arrays of integers
GENERATE_ARRAY
generates an array of values from a starting and ending value and a step value.
For example, the following query generates an array that contains all of the odd
integers from 11 to 33, inclusive:
SELECT GENERATE_ARRAY(11, 33, 2) AS odds;
/*--------------------------------------------------+
| odds |
+--------------------------------------------------+
| [11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33] |
+--------------------------------------------------*/
You can also generate an array of values in descending order by giving a negative step value:
SELECT GENERATE_ARRAY(21, 14, -1) AS countdown;
/*----------------------------------+
| countdown |
+----------------------------------+
| [21, 20, 19, 18, 17, 16, 15, 14] |
+----------------------------------*/
Generating arrays of dates
GENERATE_DATE_ARRAY
generates an array of DATEs from a starting and ending DATE and a step
INTERVAL.
You can generate a set of DATE values using GENERATE_DATE_ARRAY. For
example, this query returns the current DATE and the following
DATEs at 1 WEEK intervals up to and including a later DATE:
SELECT
GENERATE_DATE_ARRAY('2017-11-21', '2017-12-31', INTERVAL 1 WEEK)
AS date_array;
/*--------------------------------------------------------------------------+
| date_array |
+--------------------------------------------------------------------------+
| [2017-11-21, 2017-11-28, 2017-12-05, 2017-12-12, 2017-12-19, 2017-12-26] |
+--------------------------------------------------------------------------*/
Boolean type
| Name | Description |
|---|---|
BOOLBOOLEAN
|
Boolean values are represented by the keywords TRUE and
FALSE (case-insensitive). |
BOOLEAN is an alias for BOOL.
Boolean values are sorted in this order, from least to greatest:
NULLFALSETRUE
Bytes type
| Name | Description |
|---|---|
BYTES |
Variable-length binary data. |
String and bytes are separate types that can't be used interchangeably. Most functions on strings are also defined on bytes. The bytes version operates on raw bytes rather than Unicode characters. Casts between string and bytes enforce that the bytes are encoded using UTF-8.
You can convert a base64-encoded STRING expression into the BYTES format
using the
FROM_BASE64 function.
You can also convert a sequence of BYTES into a base64-encoded STRING
expression using the
TO_BASE64 function.
To learn more about the literal representation of a bytes type, see Bytes literals.
Date type
| Name | Range |
|---|---|
DATE |
0001-01-01 to 9999-12-31. |
The date type represents a Gregorian calendar date, independent of time zone. A date value doesn't represent a specific 24-hour time period. Rather, a given date value represents a different 24-hour period when interpreted in different time zones, and may represent a shorter or longer day during daylight saving time (DST) transitions. To represent an absolute point in time, use a timestamp.
Canonical format
YYYY-[M]M-[D]D
YYYY: Four-digit year.[M]M: One or two digit month.[D]D: One or two digit day.
To learn more about the literal representation of a date type, see Date literals.
Datetime type
| Name | Range |
|---|---|
DATETIME |
0001-01-01 00:00:00 to 9999-12-31 23:59:59.999999 |
A datetime value represents a Gregorian date and a time, as they might be displayed on a watch, independent of time zone. It includes the year, month, day, hour, minute, second, and subsecond. To represent an absolute point in time, use a timestamp.
Canonical format
civil_date_part[time_part]
civil_date_part:
YYYY-[M]M-[D]D
time_part:
{ |T|t}[H]H:[M]M:[S]S[.F]
YYYY: Four-digit year.[M]M: One or two digit month.[D]D: One or two digit day.{ |T|t}: A space or aTortseparator. TheTandtseparators are flags for time.[H]H: One or two digit hour (valid values from 00 to 23).[M]M: One or two digit minutes (valid values from 00 to 59).[S]S: One or two digit seconds (valid values from 00 to 60).[.F]: Up to six fractional digits (microsecond precision).
To learn more about the literal representation of a datetime type, see Datetime literals.
Numeric types
Numeric types include the following types:
INT64with aliasINT,SMALLINT,INTEGER,BIGINT,TINYINT,BYTEINTNUMERICFLOAT64
Integer type
Integers are numeric values that don't have fractional components.
| Name | Range |
|---|---|
INT64
INT
INTEGER
BIGINT
|
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
INT, SMALLINT, INTEGER, BIGINT, TINYINT, and BYTEINT are aliases
for INT64.
To learn more about the literal representation of an integer type, see Integer literals.
Decimal type
Decimal type values are numeric values with fixed decimal precision and scale. Precision is the number of digits that the number contains. Scale is how many of these digits appear after the decimal point.
This type can represent decimal fractions exactly, and is suitable for financial calculations.
| Name | Precision, Scale, and Range |
|---|---|
NUMERIC
|
Precision: 38 Scale: 9 Minimum value greater than 0 that can be handled: 1e-9 Min: -9.9999999999999999999999999999999999999E+28 Max: 9.9999999999999999999999999999999999999E+28 |
To learn more about the literal representation of a NUMERIC type,
see NUMERIC literals.
Floating point type
Floating point values are approximate numeric values with fractional components.
| Name | Description |
|---|---|
FLOAT64
|
Double precision (approximate) numeric values. |
To learn more about the literal representation of a floating point type, see Floating point literals.
Floating point semantics
When working with floating point numbers, there are special non-numeric values
that need to be considered: NaN and +/-inf
Arithmetic operators provide standard IEEE-754 behavior for all finite input values that produce finite output and for all operations for which at least one input is non-finite.
Function calls and operators return an overflow error if the input is finite
but the output would be non-finite. If the input contains non-finite values, the
output can be non-finite. In general functions don't introduce NaNs or
+/-inf. However, specific functions like IEEE_DIVIDE can return non-finite
values on finite input. All such cases are noted explicitly in
Mathematical functions.
Floating point values are approximations.
- The binary format used to represent floating point values can only represent
a subset of the numbers between the most positive number and most
negative number in the value range. This enables efficient handling of a
much larger range than would be possible otherwise.
Numbers that aren't exactly representable are approximated by utilizing a
close value instead. For example,
0.1can't be represented as an integer scaled by a power of2. When this value is displayed as a string, it's rounded to a limited number of digits, and the value approximating0.1might appear as"0.1", hiding the fact that the value isn't precise. In other situations, the approximation can be visible. - Summation of floating point values might produce surprising results because
of limited precision. For example,
(1e30 + 1) - 1e30 = 0, while(1e30 - 1e30) + 1 = 1.0. This is because the floating point value doesn't have enough precision to represent(1e30 + 1), and the result is rounded to1e30. This example also shows that the result of theSUMaggregate function of floating points values depends on the order in which the values are accumulated. In general, this order isn't deterministic and therefore the result isn't deterministic. Thus, the resultingSUMof floating point values might not be deterministic and two executions of the same query on the same tables might produce different results. - If the above points are concerning, use a decimal type instead.
Mathematical function examples
| Left Term | Operator | Right Term | Returns |
|---|---|---|---|
| Any value | + |
NaN |
NaN |
| 1.0 | + |
+inf |
+inf |
| 1.0 | + |
-inf |
-inf |
-inf |
+ |
+inf |
NaN |
Maximum FLOAT64 value |
+ |
Maximum FLOAT64 value |
Overflow error |
Minimum FLOAT64 value |
/ |
2.0 | 0.0 |
| 1.0 | / |
0.0 |
"Divide by zero" error |
Comparison operators provide standard IEEE-754 behavior for floating point input.
Comparison operator examples
| Left Term | Operator | Right Term | Returns |
|---|---|---|---|
NaN |
= |
Any value | FALSE |
NaN |
< |
Any value | FALSE |
| Any value | < |
NaN |
FALSE |
| -0.0 | = |
0.0 | TRUE |
| -0.0 | < |
0.0 | FALSE |
For more information on how these values are ordered and grouped so they can be compared, see Ordering floating point values.
String type
| Name | Description |
|---|---|
STRING |
Variable-length character (Unicode) data. |
Input string values must be UTF-8 encoded and output string values will be UTF-8 encoded. Alternate encodings like CESU-8 and Modified UTF-8 aren't treated as valid UTF-8.
All functions and operators that act on string values operate on Unicode
characters rather than bytes. For example, functions like SUBSTR and LENGTH
applied to string input count the number of characters, not bytes.
Each Unicode character has a numeric value called a code point assigned to it. Lower code points are assigned to lower characters. When characters are compared, the code points determine which characters are less than or greater than other characters.
Most functions on strings are also defined on bytes. The bytes version operates on raw bytes rather than Unicode characters. Strings and bytes are separate types that can't be used interchangeably. There is no implicit casting in either direction. Explicit casting between string and bytes does UTF-8 encoding and decoding. Casting bytes to string returns an error if the bytes aren't valid UTF-8.
To learn more about the literal representation of a string type, see String literals.
Struct type
| Name | Description |
|---|---|
STRUCT |
Container of ordered fields each with a type (required) and field name (optional). |
To learn more about the literal representation of a struct type, see Struct literals.
Declaring a struct type
STRUCT<T>
Struct types are declared using the angle brackets (< and >). The type of
the elements of a struct can be arbitrarily complex.
Examples
| Type Declaration | Meaning |
|---|---|
STRUCT<INT64>
|
Simple struct with a single unnamed 64-bit integer field. |
STRUCT<x STRUCT<y INT64, z INT64>>
|
A struct with a nested struct named x inside it. The struct
x has two fields, y and z, both of which
are 64-bit integers. |
STRUCT<inner_array ARRAY<INT64>>
|
A struct containing an array named inner_array that holds
64-bit integer elements. |
Constructing a struct
You can construct a struct using tuple syntax, typeless struct syntax, or typed struct syntax.
Tuple syntax
(expr1, expr2 [, ... ])
The output type is an anonymous struct type with anonymous fields with types matching the types of the input expressions. There must be at least two expressions specified. Otherwise this syntax is indistinguishable from an expression wrapped with parentheses.
Examples
| Syntax | Output Type | Notes |
|---|---|---|
(x, x+y) |
STRUCT<?,?> |
If column names are used (unquoted strings), the struct field data type is
derived from the column data type. x and y are
columns, so the data types of the struct fields are derived from the column
types and the output type of the addition operator. |
This syntax can also be used with struct comparison for comparison expressions
using multi-part keys, e.g., in a WHERE clause:
WHERE (Key1,Key2) IN ( (12,34), (56,78) )
Typeless struct syntax
STRUCT( expr1 [AS field_name] [, ... ])
Duplicate field names are allowed. Fields without names are considered anonymous
fields and can't be referenced by name. struct values can be NULL, or can
have NULL field values.
Examples
| Syntax | Output Type |
|---|---|
STRUCT(1,2,3) |
STRUCT<int64,int64,int64> |
STRUCT() |
STRUCT<> |
STRUCT('abc') |
STRUCT<string> |
STRUCT(1, t.str_col) |
STRUCT<int64, str_col string> |
STRUCT(1 AS a, 'abc' AS b) |
STRUCT<a int64, b string> |
STRUCT(str_col AS abc) |
STRUCT<abc string> |
Typed struct syntax
STRUCT<[field_name] field_type, ...>( expr1 [, ... ])
Typed syntax allows constructing structs with an explicit struct data type. The
output type is exactly the field_type provided. The input expression is
coerced to field_type if the two types aren't the same, and an error is
produced if the types aren't compatible. AS alias isn't allowed on the input
expressions. The number of expressions must match the number of fields in the
type, and the expression types must be coercible or literal-coercible to the
field types.
Examples
| Syntax | Output Type |
|---|---|
STRUCT<int64>(5) |
STRUCT<int64> |
STRUCT<date>("2011-05-05") |
STRUCT<date> |
STRUCT<x int64, y string>(1, t.str_col) |
STRUCT<x int64, y string> |
STRUCT<int64>(int_col) |
STRUCT<int64> |
STRUCT<x int64>(5 AS x) |
Error - Typed syntax doesn't allow AS |
Limited comparisons for structs
Structs can be directly compared using equality operators:
- Equal (
=) - Not Equal (
!=or<>) - [
NOT]IN
Notice, though, that these direct equality comparisons compare the fields of the struct pairwise in ordinal order ignoring any field names. If instead you want to compare identically named fields of a struct, you can compare the individual fields directly.
Time type
| Name | Range |
|---|---|
TIME |
00:00:00 to 23:59:59.999999 |
A time value represents a time of day, as might be displayed on a clock, independent of a specific date and time zone. To represent an absolute point in time, use a timestamp.
Canonical format
[H]H:[M]M:[S]S[.F]
[H]H: One or two digit hour (valid values from 00 to 23).[M]M: One or two digit minutes (valid values from 00 to 59).[S]S: One or two digit seconds (valid values from 00 to 60).[.F]: Up to six fractional digits (microsecond precision).
To learn more about the literal representation of a time type, see Time literals.
Timestamp type
| Name | Range |
|---|---|
TIMESTAMP |
0001-01-01 00:00:00 to 9999-12-31 23:59:59.999999 UTC |
A timestamp value represents an absolute point in time, independent of any time zone or convention such as daylight saving time (DST), with microsecond precision.
A timestamp is typically represented internally as the number of elapsed microseconds since a fixed initial point in time.
Note that a timestamp itself doesn't have a time zone; it represents the same instant in time globally. However, the display of a timestamp for human readability usually includes a Gregorian date, a time, and a time zone, in an implementation-dependent format. For example, the displayed values "2020-01-01 00:00:00 UTC", "2019-12-31 19:00:00 America/New_York", and "2020-01-01 05:30:00 Asia/Kolkata" all represent the same instant in time and therefore represent the same timestamp value.
- To represent a Gregorian date as it might appear on a calendar (a civil date), use a date value.
- To represent a time as it might appear on a clock (a civil time), use a time value.
- To represent a Gregorian date and time as they might appear on a watch, use a datetime value.
Canonical format
The canonical format for a timestamp literal has the following parts:
{
civil_date_part[time_part [time_zone]] |
civil_date_part[time_part[time_zone_offset]] |
civil_date_part[time_part[utc_time_zone]]
}
civil_date_part:
YYYY-[M]M-[D]D
time_part:
{ |T|t}[H]H:[M]M:[S]S[.F]
YYYY: Four-digit year.[M]M: One or two digit month.[D]D: One or two digit day.{ |T|t}: A space or aTortseparator. TheTandtseparators are flags for time.[H]H: One or two digit hour (valid values from 00 to 23).[M]M: One or two digit minutes (valid values from 00 to 59).[S]S: One or two digit seconds (valid values from 00 to 60).[.F]: Up to six fractional digits (microsecond precision).[time_zone]: String representing the time zone. When a time zone isn't explicitly specified, the default time zone, UTC, is used. For details, see time zones.[time_zone_offset]: String representing the offset from the Coordinated Universal Time (UTC) time zone. For details, see time zones.[utc_time_zone]: String representing the Coordinated Universal Time (UTC), usually the letterZorz. For details, see time zones.
To learn more about the literal representation of a timestamp type, see Timestamp literals.
Time zones
A time zone is used when converting from a civil date or time (as might appear on a calendar or clock) to a timestamp (an absolute time), or vice versa. This includes the operation of parsing a string containing a civil date and time like "2020-01-01 00:00:00" and converting it to a timestamp. The resulting timestamp value itself doesn't store a specific time zone, because it represents one instant in time globally.
Time zones are represented by strings in one of these canonical formats:
- Offset from Coordinated Universal Time (UTC), or the letter
Zorzfor UTC. - Time zone name from the tz database.
The following timestamps are identical because the time zone offset
for America/Los_Angeles is -08 for the specified date and time.
SELECT UNIX_MILLIS(TIMESTAMP '2008-12-25 15:30:00 America/Los_Angeles') AS millis;
SELECT UNIX_MILLIS(TIMESTAMP '2008-12-25 15:30:00-08:00') AS millis;
Specify Coordinated Universal Time (UTC)
You can specify UTC using the following suffix:
{Z|z}
You can also specify UTC using the following time zone name:
{Etc/UTC}
The Z suffix is a placeholder that implies UTC when converting an RFC
3339-format value to a TIMESTAMP value. The value Z isn't
a valid time zone for functions that accept a time zone. If you're specifying a
time zone, or you're unsure of the format to use to specify UTC, we recommend
using the Etc/UTC time zone name.
The Z suffix isn't case sensitive. When using the Z suffix, no space is
allowed between the Z and the rest of the timestamp. The following are
examples of using the Z suffix and the Etc/UTC time zone name:
SELECT TIMESTAMP '2014-09-27T12:30:00.45Z'
SELECT TIMESTAMP '2014-09-27 12:30:00.45z'
SELECT TIMESTAMP '2014-09-27T12:30:00.45 Etc/UTC'
Specify an offset from Coordinated Universal Time (UTC)
You can specify the offset from UTC using the following format:
{+|-}H[H][:M[M]]
Examples:
-08:00
-8:15
+3:00
+07:30
-7
When using this format, no space is allowed between the time zone and the rest of the timestamp.
2014-09-27 12:30:00.45-8:00
Time zone name
Format:
tz_identifier
A time zone name is a tz identifier from the tz database. For a less comprehensive but simpler reference, see the List of tz database time zones on Wikipedia.
Examples:
America/Los_Angeles
America/Argentina/Buenos_Aires
Etc/UTC
Pacific/Auckland
When using a time zone name, a space is required between the name and the rest of the timestamp:
2014-09-27 12:30:00.45 America/Los_Angeles
Note that not all time zone names are interchangeable even if they do happen to
report the same time during a given part of the year. For example,
America/Los_Angeles reports the same time as UTC-7:00 during daylight
saving time (DST), but reports the same time as UTC-8:00 outside of DST.
If a time zone isn't specified, the default time zone value is used.
Leap seconds
A timestamp is simply an offset from 1970-01-01 00:00:00 UTC, assuming there are exactly 60 seconds per minute. Leap seconds aren't represented as part of a stored timestamp.
If the input contains values that use ":60" in the seconds field to represent a leap second, that leap second isn't preserved when converting to a timestamp value. Instead that value is interpreted as a timestamp with ":00" in the seconds field of the following minute.
Leap seconds don't affect timestamp computations. All timestamp computations are done using Unix-style timestamps, which don't reflect leap seconds. Leap seconds are only observable through functions that measure real-world time. In these functions, it's possible for a timestamp second to be skipped or repeated when there is a leap second.
Daylight saving time
A timestamp is unaffected by daylight saving time (DST) because it represents a point in time. When you display a timestamp as a civil time, with a timezone that observes DST, the following rules apply:
During the transition from standard time to DST, one hour is skipped. A civil time from the skipped hour is treated the same as if it were written an hour later. For example, in the
America/Los_Angelestime zone, the hour between 2 AM and 3 AM on March 10, 2024 is skipped on a clock. The times 2:30 AM and 3:30 AM on that date are treated as the same point in time:SELECT FORMAT_TIMESTAMP("%c %Z", "2024-03-10 02:30:00 America/Los_Angeles", "UTC") AS two_thirty, FORMAT_TIMESTAMP("%c %Z", "2024-03-10 03:30:00 America/Los_Angeles", "UTC") AS three_thirty; /*------------------------------+------------------------------+ | two_thirty | three_thirty | +------------------------------+------------------------------+ | Sun Mar 10 10:30:00 2024 UTC | Sun Mar 10 10:30:00 2024 UTC | +------------------------------+------------------------------*/When there's ambiguity in how to represent a civil time in a particular timezone because of DST, the later time is chosen:
SELECT FORMAT_TIMESTAMP("%c %Z", "2024-03-10 10:30:00 UTC", "America/Los_Angeles") as ten_thirty; /*--------------------------------+ | ten_thirty | +--------------------------------+ | Sun Mar 10 03:30:00 2024 UTC-7 | +--------------------------------*/During the transition from DST to standard time, one hour is repeated. A civil time that shows a time during that hour is treated as if it's the earlier instance of that time. For example, in the
America/Los_Angelestime zone, the hour between 1 AM and 2 AM on November 3, 2024, is repeated on a clock. The time 1:30 AM on that date is treated as the earlier (DST) instance of that time.SELECT FORMAT_TIMESTAMP("%c %Z", "2024-11-03 01:30:00 America/Los_Angeles", "UTC") as one_thirty, FORMAT_TIMESTAMP("%c %Z", "2024-11-03 02:30:00 America/Los_Angeles", "UTC") as two_thirty; /*------------------------------+------------------------------+ | one_thirty | two_thirty | +------------------------------+------------------------------+ | Sun Nov 3 08:30:00 2024 UTC | Sun Nov 3 10:30:00 2024 UTC | +------------------------------+------------------------------*/