Skip to content

[BUG] Rounding.isUTC() fails for UTC timezone aliases, missing date histogram filter rewrite optimization #21219

@Hailong-am

Description

@Hailong-am

Describe the bug

Rounding.isUTC() only recognizes ZoneOffset.UTC (display name "Z") as UTC. When a timezone is passed as ZoneId.of("UTC"), ZoneId.of("Etc/UTC"), or ZoneOffset.of("+00:00"), the method returns false even though these are all semantically UTC.

This matters because isUTC() gates the filter rewrite optimization for date histogram aggregations (DateHistogramAggregatorBridge and CompositeAggregator). When isUTC() incorrectly returns false, the optimized path is skipped, resulting in slower queries.

Root Cause: ZoneId.of("UTC") and ZoneId.of("Etc/UTC") are ZoneRegion instances whose getDisplayName(TextStyle.FULL, Locale.ENGLISH) returns "Coordinated Universal Time", not "Z".

Input getDisplayName() (before) normalized().getDisplayName() (after)
ZoneId.of("UTC") Coordinated Universal Time Z
ZoneId.of("Etc/UTC") Coordinated Universal Time Z
ZoneOffset.of("+00:00") Z Z
ZoneOffset.UTC ("Z") Z Z

Fix: Call .normalized() before .getDisplayName(). ZoneId.normalized() converts all UTC-equivalent zones to ZoneOffset.UTC:

// Before
return "Z".equals(timeZone.getDisplayName(TextStyle.FULL, Locale.ENGLISH));
// After
return "Z".equals(timeZone.normalized().getDisplayName(TextStyle.FULL, Locale.ENGLISH));

Both TimeUnitRounding.isUTC() and TimeIntervalRounding.isUTC() need this fix.

Related component

Search:Aggregations

To Reproduce

  1. Send a date_histogram aggregation with "time_zone": "UTC" (or "+00:00" or "Etc/UTC")
  2. The filter rewrite optimization is skipped because Rounding.isUTC() returns false
  3. The same query with no timezone (defaults to ZoneOffset.UTC / "Z") correctly uses the optimization

This is the common case when using OpenSearch Dashboards, which sends timezone values like:

  • "UTC" — from explicit dateFormat:tz setting or moment.tz.guess()
  • "Etc/UTC" — from Timeline plugin configuration
  • "+00:00" — from moment().format('Z') fallback

Expected behavior

Rounding.isUTC() should return true for all UTC-equivalent timezone representations ("UTC", "Etc/UTC", "+00:00", "Z"), so that the date histogram filter rewrite optimization is applied correctly.

Additional Details

Version: main (3.0)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    🆕 New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions