---
title: "How to round timestamps in ClickHouse®"
excerpt: "Learn how to round timestamps in ClickHouse® using toStartOfDay, toStartOfHour, and other built-in functions with syntax examples and performance tips."
authors: "Cameron Archer"
categories: "AI Resources"
createdOn: "2025-10-03 17:22:12"
publishedOn: "2025-10-03 17:22:12"
updatedOn: "2025-10-03 17:22:12"
status: "published"
---

ClickHouse® gives you precise control over timestamp rounding through a complete set of `toStartOf*` functions that truncate DateTime and DateTime64 values to specific time boundaries. Each function targets a different granularity, from rounding down to the start of a day all the way to nanosecond precision.

This guide covers all seven timestamp rounding functions, their syntax differences, performance considerations, and how to avoid common precision errors when working with subsecond data.

## What timestamp rounding functions exist in ClickHouse®

ClickHouse® gives you a complete set of `toStartOf*` functions that round down DateTime or DateTime64 values to the beginning of specific time units. Each function targets a different granularity, from days down to nanoseconds.

The way this works is pretty straightforward: each function truncates your timestamp to remove precision below your target unit. When you use `toStartOfDay`, it removes hours, minutes, and seconds. When you use `toStartOfMinute`, it keeps hours but removes seconds and subseconds.

### toStartOfDay

The `toStartOfDay` function rounds any timestamp down to midnight of the same day.

```sql
SELECT toStartOfDay('2024-03-15 14:30:22') AS rounded;
-- Result: 2024-03-15 00:00:00
```

You can also pass an optional timezone parameter to handle day boundaries correctly across different time zones:

```sql
SELECT toStartOfDay('2024-03-15 14:30:22', 'America/New_York') AS rounded;
```

### toStartOfHour

The `toStartOfHour` function removes minutes and seconds, keeping only the hour boundary.

```sql
SELECT toStartOfHour('2024-03-15 14:30:22') AS rounded;
-- Result: 2024-03-15 14:00:00
```

This function comes in handy for hourly aggregations in time-series analytics.

### toStartOfMinute

The `toStartOfMinute` function preserves hours and minutes while removing seconds and any subsecond precision.

```sql
SELECT toStartOfMinute('2024-03-15 14:30:22.456') AS rounded;
-- Result: 2024-03-15 14:30:00
```

### toStartOfSecond

The `toStartOfSecond` function removes subsecond precision while keeping the full seconds value.

```sql
SELECT toStartOfSecond('2024-03-15 14:30:22.456789') AS rounded;
-- Result: 2024-03-15 14:30:22
```

### toStartOfMillisecond

The `toStartOfMillisecond` function works with DateTime64(3) precision and removes microsecond and nanosecond components.

```sql
SELECT toStartOfMillisecond(toDateTime64('2024-03-15 14:30:22.456789', 6)) AS rounded;
-- Result: 2024-03-15 14:30:22.456
```

Your input timestamp needs DateTime64 precision to contain subsecond data, otherwise you won't see any difference.

### toStartOfMicrosecond

The `toStartOfMicrosecond` function requires DateTime64(6) precision and removes only nanosecond precision.

```sql
SELECT toStartOfMicrosecond(toDateTime64('2024-03-15 14:30:22.456789123', 9)) AS rounded;
-- Result: 2024-03-15 14:30:22.456789
```

### toStartOfNanosecond

The `toStartOfNanosecond` function works with DateTime64(9) precision and essentially returns the input unchanged since nanoseconds are the highest precision available in ClickHouse®.

```sql
SELECT toStartOfNanosecond(toDateTime64('2024-03-15 14:30:22.456789123', 9)) AS rounded;
-- Result: 2024-03-15 14:30:22.456789123
```

## Syntax cheat sheet for each granularity

Here's a quick reference for all timestamp rounding functions and what they expect:

| Function | Input Type | Optional Timezone | Return Type | Example Result |
| -------- | ---------- | ----------------- | ----------- | --------------- |
| `toStartOfDay` | DateTime/DateTime64 | Yes | DateTime | `2024-03-15 00:00:00` |
| `toStartOfHour` | DateTime/DateTime64 | Yes | DateTime | `2024-03-15 14:00:00` |
| `toStartOfMinute` | DateTime/DateTime64 | Yes | DateTime | `2024-03-15 14:30:00` |
| `toStartOfSecond` | DateTime/DateTime64 | Yes | DateTime | `2024-03-15 14:30:22` |
| `toStartOfMillisecond` | DateTime64(≥3) | Yes | DateTime64(3) | `2024-03-15 14:30:22.456` |
| `toStartOfMicrosecond` | DateTime64(≥6) | Yes | DateTime64(6) | `2024-03-15 14:30:22.456789` |
| `toStartOfNanosecond` | DateTime64(9) | Yes | DateTime64(9) | `2024-03-15 14:30:22.456789123` |

### Function Signatures

All `toStartOf*` functions follow the same signature pattern:

```sql
toStartOfX(timestamp [, timezone])
```

The timestamp parameter accepts either DateTime or DateTime64 types, though subsecond functions require DateTime64 with appropriate precision.

### Required and Optional Arguments

The timezone parameter becomes crucial when dealing with day boundaries or daylight saving time transitions. Without it, ClickHouse® uses the server's default timezone, which might not match your data's actual timezone context.

For DateTime64 inputs, the precision has to match or exceed the target granularity. You can't round to milliseconds with a DateTime64(1) input because there's no millisecond data to work with.

## Choosing between toStartOfX, toStartOfInterval, and date_trunc

ClickHouse® offers three approaches for timestamp rounding, each with different trade-offs for performance and flexibility.

The `toStartOf*` functions provide the fastest performance for fixed intervals since they're optimized for specific time units. The `toStartOfInterval` function offers more flexibility for dynamic intervals but with slightly higher overhead. There's also `date_trunc` for SQL compatibility.

### Flexibility Versus Performance

Use `toStartOf*` functions when you know the exact granularity at query time:

```sql
-- Fast and direct
SELECT toStartOfHour(timestamp) FROM events;
```

Use `toStartOfInterval` when the interval comes from a parameter or variable:

```sql
-- More flexible but slightly slower
SELECT toStartOfInterval(timestamp, INTERVAL 1 HOUR) FROM events;
```

### Porting SQL From Postgres

ClickHouse® includes a `date_trunc` function for SQL compatibility with PostgreSQL, but the native `toStartOf*` functions typically perform better:

```sql
-- PostgreSQL style (works but not optimal)
SELECT date_trunc('hour', timestamp) FROM events;

-- ClickHouse® native (preferred)
SELECT toStartOfHour(timestamp) FROM events;
```

The `date_trunc` function essentially wraps the native functions internally, adding a small overhead that you probably won't notice in most queries.

## Handling time zones and DateTime64 precision

Time zones significantly impact rounding results, especially for day and hour boundaries. ClickHouse® processes timestamps in UTC by default, but your data might represent times in different zones.

DateTime64 precision determines which subsecond functions you can use effectively. Mismatched precision often leads to unexpected results or type errors.

### Passing a Time Zone Parameter

Here's how timezone affects day rounding:

```sql
-- UTC interpretation
SELECT toStartOfDay('2024-03-15 02:30:22') AS utc_day;
-- Result: 2024-03-15 00:00:00

-- New York interpretation (EST/EDT)
SELECT toStartOfDay('2024-03-15 02:30:22', 'America/New_York') AS ny_day;
-- Result: 2024-03-15 05:00:00 (displayed in UTC)
```

The timezone parameter ensures the day boundary calculation happens in the correct local time before converting back to UTC for storage. This becomes especially important during daylight saving time transitions.

### Avoiding Precision Loss

Match your DateTime64 precision to your rounding needs:

```sql
-- This works correctly
SELECT toStartOfMillisecond(toDateTime64('2024-03-15 14:30:22.456789', 6));

-- This loses precision unnecessarily
SELECT toStartOfSecond(toDateTime64('2024-03-15 14:30:22.456789', 9));
```

Always use the minimum precision that captures your required granularity to avoid storage overhead. Higher precision means more storage space and potentially slower queries.

## Performance impact and index considerations

Timestamp rounding affects query performance in several ways, particularly around partition pruning and index utilization. The choice of rounding function can either help or hurt your query optimization.

When your table partitions align with your rounding granularity, ClickHouse® can eliminate entire partitions from queries. When they don't align, you might scan more data than necessary.

### Partition Pruning Effects

Here's what happens with different alignment scenarios:

```sql
-- If partitioned by day, this enables partition pruning
SELECT COUNT(*) FROM events
WHERE toStartOfDay(timestamp) = '2024-03-15';

-- This prevents partition pruning
SELECT COUNT(*) FROM events
WHERE toStartOfHour(timestamp) = '2024-03-15 14:00:00';
```

Match your rounding functions to your partitioning scheme when possible. If you partition by day but frequently query by hour, consider whether your partitioning strategy makes sense.

### Benchmark Results

In general, the more specific `toStartOf*` functions outperform `toStartOfInterval` by 10-15% for equivalent operations. The performance difference becomes more pronounced with higher query volumes.

Subsecond rounding functions add minimal overhead compared to second-level rounding since they primarily manipulate the precision rather than recalculating time boundaries. The real cost comes from the DateTime64 operations themselves.

## Common errors and how to fix them

Two categories of errors frequently occur when working with timestamp rounding: interval specification mistakes and type precision mismatches. Both are pretty easy to fix once you know what to look for.

### Unknown Interval Unit

The `toStartOfInterval` function requires specific interval syntax:

```sql
-- Wrong: this will cause an error
SELECT toStartOfInterval(timestamp, '1 hour');

-- Correct: use INTERVAL keyword
SELECT toStartOfInterval(timestamp, INTERVAL 1 HOUR);
```

Valid interval units include SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, and YEAR. You can't use arbitrary strings or abbreviations.

### Type Mismatch With DateTime64

Subsecond rounding functions expect appropriate DateTime64 precision:

```sql
-- Error: precision too low for milliseconds
SELECT toStartOfMillisecond(toDateTime64('2024-03-15 14:30:22', 1));

-- Fixed: use precision 3 or higher
SELECT toStartOfMillisecond(toDateTime64('2024-03-15 14:30:22.456', 3));
```

The precision number in DateTime64(n) has to be at least 3 for milliseconds, 6 for microseconds, and 9 for nanoseconds. Otherwise, the function doesn't have enough precision to work with.

## Step-by-step: build a ClickHouse®-based analytics API that returns rounded data

Let's create a complete example that ingests timestamped events and exposes an [API endpoint](https://www.tinybird.co/docs/api-reference/pipe-api/api-endpoints) returning hourly aggregated data using timestamp rounding.

This walkthrough shows how timestamp rounding integrates into real-world analytics workflows, from data ingestion through API deployment. You'll see exactly how the rounding functions work in practice.

### 1. Create the data source

First, create a [data source](https://www.tinybird.co/docs/get-data-in/data-sources) to store your timestamped events:

```bash
tb datasource create events_raw \
  --format ndjson \
  --schema "timestamp DateTime64(3), user_id UInt32, event_type String, value Float64"
```

Then ingest some sample data:

```json
{"timestamp": "2024-03-15 14:23:45.123", "user_id": 1001, "event_type": "click", "value": 1.0}
{"timestamp": "2024-03-15 14:45:12.456", "user_id": 1002, "event_type": "purchase", "value": 29.99}
{"timestamp": "2024-03-15 15:12:33.789", "user_id": 1001, "event_type": "click", "value": 1.0}
```

### 2. Write the pipe query

Create a [pipe](https://www.tinybird.co/docs/forward/work-with-data/pipes) that aggregates events by hour using timestamp rounding:

```tinybird
NODE hourly_aggregation
SQL >
    SELECT
        toStartOfHour(timestamp) AS hour,
        event_type,
        COUNT(*) AS event_count,
        SUM(value) AS total_value,
        COUNT(DISTINCT user_id) AS unique_users
    FROM events_raw
    WHERE timestamp >= now() - INTERVAL 7 DAY
    GROUP BY hour, event_type
    ORDER BY hour DESC, event_type

TYPE materialized
DATASOURCE hourly_events
```

The `toStartOfHour` function ensures all events within the same hour get grouped together, regardless of their exact timestamp. Events at 14:23:45 and 14:45:12 both round to 14:00:00.

### 3. Deploy and call the endpoint

Deploy your pipe to create the API endpoint:

```bash
tb --cloud deploy
```

Then call your new endpoint:

```bash
curl -H "Authorization: Bearer <your_token>" \
  "https://api.tinybird.co/v0/pipes/hourly_aggregation.json"
```

The response returns neatly aggregated data with hour boundaries:

```json
{
  ...,
  "data": [
    {"hour": "2024-03-15 15:00:00", "event_type": "click", "event_count": 1, "total_value": 1.0, "unique_users": 1},
    {"hour": "2024-03-15 14:00:00", "event_type": "click", "event_count": 1, "total_value": 1.0, "unique_users": 1},
    {"hour": "2024-03-15 14:00:00", "event_type": "purchase", "event_count": 1, "total_value": 29.99, "unique_users": 1}
  ],
  ...
}
```

## Ship faster with managed ClickHouse®

[Tinybird](https://www.tinybird.co) provides a [managed ClickHouse® platform](https://www.tinybird.co/clickhouse) that includes the timestamp rounding capabilities described above, along with developer tooling to accelerate API development. The platform manages infrastructure scaling, security, and performance optimization.

Tinybird supports use cases such as user-facing dashboards, real-time personalization, and content recommendation systems that require fast data access, while reducing operational overhead.

[Sign up for free](https://cloud.tinybird.co/signup) to build and test your first ClickHouse®-based API in a few minutes.

## FAQs about rounding timestamps in ClickHouse®

### Can I round timestamps when creating a materialized view?

Yes, timestamp rounding functions work perfectly in [materialized view](https://www.tinybird.co/docs/work-with-data/optimize/materialized-views) SELECT statements and often improve aggregation performance by pre-computing time buckets. This approach reduces query time since the rounding calculation happens once during ingestion rather than repeatedly during queries.

### How do I apply rounding inside a window function?

Use timestamp rounding functions in the PARTITION BY or ORDER BY clauses of window functions for time-based windowing. For example: `ROW_NUMBER() OVER (PARTITION BY toStartOfHour(timestamp) ORDER BY value DESC)` creates row numbers within each hour bucket.

## Additional resources

- [toStartOfDay function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofday)
- [toStartOfHour function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofhour)
- [toStartOfMinute function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofminute)
- [toStartOfSecond function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofsecond)
- [toStartOfMillisecond function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofmillisecond)
- [toStartOfMicrosecond function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofmicrosecond)
- [toStartOfNanosecond function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofnanosecond)
- [toStartOfInterval function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#tostartofinterval)
- [date_trunc function](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#date-trunc)
- [DateTime64 data type](https://clickhouse.com/docs/en/sql-reference/data-types/datetime64)
- [Time zone handling in ClickHouse®](https://clickhouse.com/docs/en/sql-reference/functions/date-time-functions#timezone-functions)
- [How to convert DateTimes to a different timezone in ClickHouse®](https://www.tinybird.co/blog-posts/convert-datetime-timezone-clickhouse-totimezone)
- [How to handle DST-aware UTC offset calculations in ClickHouse®](https://www.tinybird.co/blog-posts/handle-dst-aware-utc-offset-clickhouse)
- [How to get the current query timestamp with timezone in ClickHouse®](https://www.tinybird.co/blog-posts/clickhouse-current-timestamp-timezone)
