Google BigQuery

BigQuery conversion functions: every type-to-type conversion

A lookup for converting between data types in BigQuery: which function turns a string into a number, a date or a timestamp, how to go back to text, how bytes and JSON convert, and when BigQuery converts for you. Each example shows the result of a real run.

Google BigQueryIevgen Krasovytskyi5 min read

BigQuery conversion functions: every type-to-type conversion

BigQuery converts between data types in three ways: CAST for the standard conversions, the PARSE_ functions when a string needs a format, and the FORMAT_ functions to go back to text. This page is the lookup: find the conversion you need in the table, then the section with the tested example.

From To Use
STRING INT64, FLOAT64, BOOL CAST, SAFE_CAST
STRING with separators NUMERIC PARSE_NUMERIC
STRING DATE CAST, PARSE_DATE
STRING TIMESTAMP PARSE_TIMESTAMP
DATE, TIMESTAMP STRING FORMAT_DATE, FORMAT_TIMESTAMP
number STRING CAST, FORMAT
Unix seconds TIMESTAMP TIMESTAMP_SECONDS
BYTES STRING CAST, SAFE_CONVERT_BYTES_TO_STRING
struct, array JSON text TO_JSON_STRING
JSON text value JSON_VALUE then SAFE_CAST

Results below come from a run in BigQuery on 6 October 2026. Google’s reference is the conversion functions page.

Note: Originally published in January 2024. Fully updated in October 2026 with re-run examples and a section on implicit conversion.

CAST and SAFE_CAST

CAST and SAFE_CAST

CAST(x AS type) handles most conversions and stops the query on a value it cannot convert. SAFE_CAST returns NULL for that value instead.

SELECT
  CAST('42' AS INT64),            -- 42
  CAST(42 AS STRING),             -- '42'
  SAFE_CAST('1,200' AS INT64),    -- NULL
  CAST(TRUE AS INT64);            -- 1

The details, including how CAST rounds floats and why '1,200' fails, are in CAST and SAFE_CAST in BigQuery.

Strings to numbers: PARSE_NUMERIC

Strings to numbers: PARSE_NUMERIC

CAST rejects a number written with thousands separators. PARSE_NUMERIC accepts it:

SELECT
  PARSE_NUMERIC('1,234.56'),       -- 1234.56
  PARSE_NUMERIC(' -12.5 '),        -- -12.5
  PARSE_BIGNUMERIC('1e3'),         -- 1000
  SAFE.PARSE_NUMERIC('12abc');     -- NULL

It ignores commas and surrounding spaces and returns an exact NUMERIC, which is the right type for money. For values that may be dirty, add the SAFE. prefix.

One caution: PARSE_NUMERIC treats the comma as a thousands separator. A European-style 1.234,56 needs its separators swapped with REPLACE first.

The Turning Point

OWOX Data Marts

See your first report built in real time. 15 minutes.

  1. Connect your data warehouse
  2. Pick your metrics
  3. Get a live Google Sheets report

In the time it takes to write a ticket. Then imagine never writing that ticket again.

Book a Demo

We'll use your actual use case

Strings to dates and timestamps

Strings to dates and timestamps

A string in YYYY-MM-DD form casts directly. Anything else needs a format string.

SELECT
  PARSE_DATE('%d/%m/%Y', '06/10/2026'),
  -- 2026-10-06
  PARSE_DATETIME('%Y-%m-%d %H:%M:%S',
                 '2026-10-06 09:00:00'),
  -- 2026-10-06T09:00:00
  PARSE_TIMESTAMP('%d/%m/%Y %H:%M',
                  '06/10/2026 23:30',
                  'Asia/Tokyo');
  -- 2026-10-06 14:30:00 UTC

The third argument of PARSE_TIMESTAMP is the time zone the text was written in. Leave it out and BigQuery assumes UTC, which shifts every value by the offset. That is the difference between the types in one line; the full explanation is in DATE vs DATETIME vs TIMESTAMP.

All three accept the SAFE. prefix, and on imported data they should have it. See date functions for the format elements.

Dates, timestamps and numbers to strings

Dates, timestamps and numbers to strings

SELECT
  FORMAT_DATE('%Y-%m', DATE '2026-10-06'),
  -- 2026-10
  FORMAT_TIMESTAMP('%Y-%m-%dT%H:%M:%SZ',
    TIMESTAMP '2026-10-06 23:30:00+00'),
  -- 2026-10-06T23:30:00Z
  STRING(TIMESTAMP '2026-10-06 23:30:00+00',
         'Asia/Tokyo');
  -- 2026-10-07 08:30:00+09

For numbers, CAST gives the plain value and FORMAT gives control over the layout:

SELECT
  CAST(1234567.891 AS STRING),  -- 1234567.891
  FORMAT('%.2f', 3.14159),      -- 3.14
  FORMAT("%'d", 1234567);       -- 1,234,567

Format at the last step. A formatted number is a string: it sorts alphabetically and cannot be summed. Keep the numeric column for calculations and format only what is displayed.

Unix time

Unix time

SELECT
  UNIX_SECONDS(TIMESTAMP '2026-10-06 00:00:00+00'),
  -- 1791244800
  TIMESTAMP_SECONDS(1791244800),
  -- 2026-10-06 00:00:00 UTC
  TIMESTAMP_MILLIS(1791244800000);
  -- 2026-10-06 00:00:00 UTC

Check the unit before converting. Seconds, milliseconds and microseconds each have their own function, and using the wrong one gives a date in 1970 or an out-of-range error. More in timestamp functions.

Bytes and strings

Bytes and strings

SELECT
  CAST(b'hello' AS STRING),                 -- hello
  CAST('hello' AS BYTES),                   -- b'hello'
  SAFE_CONVERT_BYTES_TO_STRING(b'\xff'),    -- �
  TO_BASE64(b'hello'),                      -- aGVsbG8=
  FROM_BASE64('aGVsbG8='),                  -- b'hello'
  TO_HEX(b'hello'),                         -- 68656c6c6f
  FROM_HEX('68656c6c6f');                   -- b'hello'

CAST(bytes AS STRING) requires valid UTF-8 and fails with “Invalid cast of bytes to UTF8 string” otherwise. SAFE_CONVERT_BYTES_TO_STRING never fails: it replaces each invalid byte with the Unicode replacement character.

To move between characters and their code points:

SELECT
  TO_CODE_POINTS('ab'),             -- [97, 98]
  CODE_POINTS_TO_STRING([97, 98]);  -- ab

JSON

JSON

To turn a row or an array into JSON text:

SELECT
  TO_JSON_STRING(
    STRUCT('ana' AS customer, 120 AS amount)),
  -- {"customer":"ana","amount":120}
  TO_JSON_STRING([1, 2, 3]);
  -- [1,2,3]

To get a typed value out of JSON text, extract it as a string and cast it:

SELECT SAFE_CAST(
  JSON_VALUE('{"a":"1"}', '$.a') AS INT64);
-- 1

JSON_VALUE always returns a STRING, so a number inside JSON is still text until you cast it. This is covered in depth in JSON parsing and conversion.

Converting every element of an array

Converting every element of an array

There is no single function for this. Use a subquery over UNNEST:

SELECT ARRAY(
  SELECT CAST(x AS INT64)
  FROM UNNEST(['1', '2', '3']) AS x
);
-- [1, 2, 3]

To go from an array to one string, ARRAY_TO_STRING(arr, ','); from a string to an array, SPLIT(s, ','). Both are in string functions.

When BigQuery converts for you

When BigQuery converts for you

BigQuery performs some conversions without being asked. The one you meet most often is a string literal compared to a date:

SELECT DATE '2026-10-06' = '2026-10-06';
-- true

The literal is converted to a DATE, so WHERE order_date = '2026-10-06' works. It works only for a literal. A STRING column compared to a DATE column is an error, and you must cast one side yourself. The rules are in Google’s conversion rules.

Integers also convert to FLOAT64 or NUMERIC automatically when an expression mixes them. Nothing converts automatically from a string column to a number.

Three checks before trusting a conversion

Three checks before trusting a conversion

  1. Count what SAFE dropped. COUNTIF(raw IS NOT NULL AND SAFE_CAST(raw AS INT64) IS NULL) is the number of values that silently became NULL.
  2. Name the time zone in every conversion to or from TIMESTAMP.
  3. Use NUMERIC for money. FLOAT64 is approximate.

Where the conversion should live

Where the conversion should live

A conversion decides what a column means. Whether a revenue string with a comma became 1234.56 or NULL, and which time zone turned a timestamp into a day, is settled by one function call in one query. When that call is repeated in ten reports, it is eventually written two different ways.

So do it once, in the query that prepares the data, and let reports read typed columns from there. In OWOX Data Marts that query is a Data Mart: your SQL, with its description and owner, run in your warehouse. OWOX does not convert or clean the data. It keeps the conversion you wrote as the single one in use.

Your New Normal

Turn your data into decisions.

Governed data marts give you the clean foundation ML needs to actually work.

  • No AI hallucinations
  • Analyst-governed definitions
  • Every number traces to SQL
Get started free

FAQ

Frequently Asked Questions

How do I convert a string to a TIMESTAMP in BigQuery?

PARSE_TIMESTAMP(format, string, time_zone). The third argument is the zone the text was written in; without it BigQuery assumes UTC. PARSE_TIMESTAMP('%d/%m/%Y %H:%M', '06/10/2026 23:30', 'Asia/Tokyo') returns 2026-10-06 14:30:00 UTC.

How do I convert BYTES to STRING in BigQuery?

CAST(b AS STRING) when the bytes are valid UTF-8. If they may not be, SAFE_CONVERT_BYTES_TO_STRING(b) never fails and replaces each invalid byte with the Unicode replacement character. For an encoded form, use TO_BASE64 or TO_HEX.

How do I convert a string to a DATE in BigQuery?

CAST(s AS DATE) when the string is in YYYY-MM-DD form. For any other layout, PARSE_DATE with a format string: PARSE_DATE('%d/%m/%Y', '06/10/2026') returns 2026-10-06. Use SAFE.PARSE_DATE on imported data so one bad value does not stop the query.

How do I convert a string with commas to a number in BigQuery?

Use PARSE_NUMERIC, which ignores thousands separators and surrounding spaces: PARSE_NUMERIC('1,234.56') returns 1234.56. CAST('1,234.56' AS NUMERIC) fails.

What are conversion functions in BigQuery?

Functions that change a value from one data type to another. CAST and SAFE_CAST cover the standard conversions, the PARSE_ functions turn formatted strings into numbers, dates and timestamps, and the FORMAT_ functions turn values back into text.

Does BigQuery convert a string to a date automatically?

Only a string literal. WHERE order_date = '2026-10-06' works because the literal is converted to a DATE. A STRING column compared to a DATE column is an error, and one side has to be cast explicitly.

How do I convert a number to a string with formatting in BigQuery?

CAST(x AS STRING) gives the plain value. FORMAT gives control: FORMAT('%.2f', 3.14159) returns 3.14, and FORMAT with the pattern %'d adds thousands separators, turning 1234567 into 1,234,567.

Who wrote this

Ievgen Krasovytskyi

Ievgen Krasovytskyi · Head of Marketing

Ievgen Krasovytskyi is the Head of Marketing at OWOX, leading strategy across content, SEO, product marketing, and AI-powered automation. With deep expertise in analytics infrastructure, data warehouses, and marketing technology, he builds systems that connect marketing performance to business outcomes. Ievgen writes about SaaS growth, analytics workflows, and the future of AI in marketing operations.