Google BigQuery

DATE vs DATETIME vs TIMESTAMP: how to choose the right SQL date type

DATE is a calendar day. DATETIME is a date and a clock time with no time zone. TIMESTAMP is one exact moment, the same everywhere. This guide shows how the three behave in BigQuery, which to choose for which column, and how to convert between them without shifting a day.

Google BigQueryVadym Kramarenko6 min read

DATE vs DATETIME vs TIMESTAMP: how to choose the right SQL date type

DATE is a calendar day. DATETIME is a day and a clock reading, with no time zone attached. TIMESTAMP is one exact moment, the same for everyone on Earth. Choose by what the value means, not by how much detail you want to keep.

Type Holds Time zone Example
DATE year, month, day none 2026-10-06
DATETIME day and time as read off a clock none 2026-10-06 09:00:00
TIMESTAMP an absolute point in time stored as UTC 2026-10-06 13:00:00 UTC

The short rule: if the value answers “when did it happen”, use TIMESTAMP. If it answers “what did the clock on the wall say”, use DATETIME. If only the day matters, use DATE.

The examples below are BigQuery SQL and were run on 6 October 2026. Other databases use the same three ideas under slightly different names, so check your own engine’s reference before copying a type name.

Note: Originally published in April 2024. Fully updated in October 2026 with re-run examples, including what happens across a daylight saving change.

DATETIME vs TIMESTAMP: the difference that matters

DATETIME vs TIMESTAMP: the difference that matters

A TIMESTAMP is a moment. Nine in the morning in New York and three in the afternoon in Paris are the same TIMESTAMP:

SELECT
  TIMESTAMP '2026-10-06 09:00:00 America/New_York'
  = TIMESTAMP '2026-10-06 15:00:00 Europe/Paris';
-- true

BigQuery does not store the zone you typed. It converts the value to UTC, keeps that, and shows it back in UTC unless you ask for another zone.

A DATETIME is what a clock showed, and nothing else. 2026-10-06 09:00:00 as a DATETIME is nine o’clock somewhere. Until you say where, it is not a moment at all:

SELECT
  TIMESTAMP(DATETIME '2026-10-06 09:00:00',
            'America/New_York'),
  -- 2026-10-06 13:00:00 UTC
  TIMESTAMP(DATETIME '2026-10-06 09:00:00');
  -- 2026-10-06 09:00:00 UTC

The same DATETIME becomes two moments four hours apart, depending on the zone you supply. Leave the zone out and BigQuery assumes UTC, which is rarely what the person who entered “9:00” meant.

The daylight saving test

Clocks in New York go back one hour on 1 November 2026. Count the hours from noon on 31 October to noon on 1 November, both ways:

SELECT
  TIMESTAMP_DIFF(
    TIMESTAMP '2026-11-01 12:00:00 America/New_York',
    TIMESTAMP '2026-10-31 12:00:00 America/New_York',
    HOUR),
  -- 25
  DATETIME_DIFF(
    DATETIME '2026-11-01 12:00:00',
    DATETIME '2026-10-31 12:00:00',
    HOUR);
  -- 24

Twenty-five real hours passed. DATETIME says twenty-four, because it only knows the clock readings. Any duration, delay or “time since” belongs in TIMESTAMP.

DATE vs DATETIME

DATE vs DATETIME

A DATE has no time of day. Converting it to a DATETIME gives midnight:

SELECT CAST(DATE '2026-10-06' AS DATETIME);
-- 2026-10-06T00:00:00

Use DATE when the time would be noise or a lie: a birthday, an invoice date, a reporting day, the day a campaign ran. Storing those as DATETIME adds a midnight that every later comparison has to work around.

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

DATE vs TIMESTAMP: one moment, two days

DATE vs TIMESTAMP: one moment, two days

The same moment falls on different calendar days in different places. This is the conversion that shifts numbers between days in a report:

SELECT
  DATE(TIMESTAMP '2026-10-06 23:30:00+00'),
  -- 2026-10-06
  DATE(TIMESTAMP '2026-10-06 23:30:00+00',
       'Asia/Tokyo');
  -- 2026-10-07

An order placed at 23:30 UTC belongs to the 6th in UTC and to the 7th in Tokyo. Whenever you turn a TIMESTAMP into a DATE, name the time zone. Without it BigQuery uses UTC, and a business that closes its day in another zone gets daily totals that never match finance.

How to choose, column by column

How to choose, column by column

The column is Type Why
an event time: click, order, login TIMESTAMP it happened at one moment
a load or update time TIMESTAMP you will compute delays from it
a reporting day, already assigned to a zone DATE the zone decision has been made
a birthday, a due date, a holiday DATE no time of day exists
a local schedule: “store opens 09:00” DATETIME or TIME it means 09:00 wherever the store is
a local time from a system that never recorded the zone DATETIME do not pretend to know the moment

The last row is the honest use of DATETIME. If a source gives you 2026-10-06 09:00:00 and no zone, loading it as TIMESTAMP asserts it was UTC. Keep it as DATETIME, and convert it with an explicit zone once you know which one applies.

A common and sound pattern is to store the TIMESTAMP and derive the DATE in the query that prepares the data for reporting, with the business time zone written once in that query.

Converting between the three

Converting between the three

SELECT
  -- TIMESTAMP to local clock time
  DATETIME(TIMESTAMP '2026-10-06 23:30:00+00',
           'America/New_York'),
  -- 2026-10-06T19:30:00

  -- TIMESTAMP to local day
  DATE(TIMESTAMP '2026-10-06 23:30:00+00',
       'America/New_York'),
  -- 2026-10-06

  -- local clock time to TIMESTAMP
  TIMESTAMP(DATETIME '2026-10-06 19:30:00',
            'America/New_York'),
  -- 2026-10-06 23:30:00 UTC

  -- DATE to TIMESTAMP: midnight UTC
  CAST(DATE '2026-10-06' AS TIMESTAMP);
  -- 2026-10-06 00:00:00 UTC

Every conversion that crosses the line between “a moment” and “a clock reading” takes a time zone argument. If you did not write one, UTC was used.

To show a timestamp in a local zone as text:

SELECT FORMAT_TIMESTAMP(
  '%Y-%m-%d %H:%M %Z',
  TIMESTAMP '2026-10-06 23:30:00+00',
  'Europe/Kyiv');
-- 2026-10-07 02:30 UTC+3

Each type has its own set of functions: date functions, datetime functions and timestamp functions. For casting from strings, see CAST and SAFE_CAST.

Range, precision and storage in BigQuery

Range, precision and storage in BigQuery

  • All three cover years 0001 to 9999.
  • DATETIME and TIMESTAMP keep microseconds.
  • Each value takes 8 logical bytes, whichever of the three you choose. There is no storage reason to prefer DATE over TIMESTAMP.

Sizes are from Google’s data type reference, checked October 2026.

A type does affect cost in another way: a table can be partitioned by a DATE, DATETIME or TIMESTAMP column, and a filter on that column limits how much data a query scans.

Mistakes these types cause

Mistakes these types cause

Comparing a DATE to a TIMESTAMP. BigQuery refuses with “No matching signature for operator =”. Convert one side, with a zone: DATE(ts, 'Europe/Paris') = d.

Filtering a TIMESTAMP with BETWEEN two dates. The upper bound is midnight at the start of the last day, so that day’s events are dropped. Use >= start AND < day_after_end.

Loading local times as TIMESTAMP. Every value is off by the UTC offset, and by a different amount in summer and winter.

Joining a table in UTC days to a table in local days. Both columns are DATE, the join works, and rows near midnight land on the wrong day. Nothing errors.

Using DATETIME to measure duration. Correct on most days, wrong by an hour twice a year.

The type is a decision someone made

The type is a decision someone made

Most of those mistakes share a cause: the time zone decision was made silently, inside a query, by one function call without a second argument. The column that comes out is a perfectly valid DATE, and nothing in it says “UTC” or “New York”.

That is why the conversion should happen once and be written down. In OWOX Data Marts the query that turns event timestamps into reporting days is a Data Mart: your SQL, with the zone in it, saved with a description and an owner and run in your warehouse. Reports read the day from that one definition. OWOX does not pick the time zone or convert anything on its own. It keeps your choice in one place where the next person can read it.

Data Setup tab of the Unified Ad Spend Data Mart in OWOX Data Marts, defined as SQL on Google BigQuery, validated, with its scan size shown – the conversion from timestamp to reporting day is one line in one query

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

Which type should a reporting date column be?

DATE, derived from the event TIMESTAMP with the business time zone written explicitly in the query that prepares the data. Keep the TIMESTAMP as well, so the day can be recomputed if the zone decision changes.

How much storage do DATE, DATETIME and TIMESTAMP use in BigQuery?

8 logical bytes each, according to Google's data type reference (checked October 2026). There is no storage saving in choosing DATE over TIMESTAMP.

How do I keep dates consistent across time zones?

Store event times as TIMESTAMP, and name the time zone every time you convert one to a DATE or DATETIME: DATE(ts, 'Asia/Tokyo'). Without the argument BigQuery uses UTC.

Does BigQuery store the time zone in a TIMESTAMP?

No. BigQuery converts the value to UTC when it is written and keeps only that. The zone you typed is not kept. To show the value in a local zone, pass the zone to DATETIME(), DATE() or FORMAT_TIMESTAMP().

What is the difference between DATE, DATETIME and TIMESTAMP?

DATE is a calendar day with no time. DATETIME is a day and a clock time with no time zone. TIMESTAMP is one absolute moment, stored in UTC, that is the same everywhere.

When should I use TIMESTAMP instead of DATETIME?

Whenever the value records when something happened: a click, an order, a load time. TIMESTAMP is the only one of the two that measures duration correctly. Across the daylight saving change in New York on 1 November 2026, TIMESTAMP_DIFF counts 25 hours between two noons and DATETIME_DIFF counts 24.

Who wrote this

Vadym Kramarenko

Vadym Kramarenko · Growth Marketing Manager

Vadym Kramarenko is a Growth Marketing Manager at OWOX, where he drives user acquisition and product-led growth strategies. He hosts the OWOX podcast, interviewing analytics professionals about data-driven marketing, attribution, and reporting best practices. Vadym specializes in turning complex analytics concepts into practical, actionable marketing frameworks.