This is an automated email from the ASF dual-hosted git repository.

rahulvats pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new 88f136fe903 fix(ui): use ISO dates in Gantt chart for cross-browser 
consistency (#61250) (#62784)
88f136fe903 is described below

commit 88f136fe90347d29b6114a9a968d04533b2f3b6f
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Tue Mar 3 13:10:45 2026 +0100

    fix(ui): use ISO dates in Gantt chart for cross-browser consistency 
(#61250) (#62784)
    
    (cherry picked from commit 705107621ca10fed635b0374ab1b9ca46b11766f)
    
    Co-authored-by: yuseok89 <[email protected]>
---
 .../src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
index 54d2c476b41..2dc9ec6c0f6 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
@@ -52,7 +52,6 @@ import { useGridStructure } from 
"src/queries/useGridStructure";
 import { useGridTiSummaries } from "src/queries/useGridTISummaries";
 import { getComputedCSSVariableValue } from "src/theme";
 import { isStatePending, useAutoRefresh } from "src/utils";
-import { DEFAULT_DATETIME_FORMAT_WITH_TZ, formatDate } from 
"src/utils/datetimeUtils";
 
 import { createHandleBarClick, createHandleBarHover, createChartOptions } from 
"./utils";
 
@@ -144,8 +143,6 @@ export const Gantt = ({ limit, runType, triggeringUser }: 
Props) => {
 
   const isLoading = runsLoading || structureLoading || summariesLoading || 
tiLoading;
 
-  const currentTime = 
dayjs().tz(selectedTimezone).format(DEFAULT_DATETIME_FORMAT_WITH_TZ);
-
   const data = useMemo(() => {
     if (isLoading || runId === "") {
       return [];
@@ -159,15 +156,15 @@ export const Gantt = ({ limit, runType, triggeringUser }: 
Props) => {
         const gridSummary = gridSummaries.find((ti) => ti.task_id === node.id);
 
         if ((node.isGroup ?? node.is_mapped) && gridSummary) {
-          // Use min/max times from grid summary
+          // Use min/max times from grid summary; ISO so time scale and bar 
positions render consistently across browsers
           return {
             isGroup: node.isGroup,
             isMapped: node.is_mapped,
             state: gridSummary.state,
             taskId: gridSummary.task_id,
             x: [
-              formatDate(gridSummary.min_start_date, selectedTimezone, 
DEFAULT_DATETIME_FORMAT_WITH_TZ),
-              formatDate(gridSummary.max_end_date, selectedTimezone, 
DEFAULT_DATETIME_FORMAT_WITH_TZ),
+              dayjs(gridSummary.min_start_date).toISOString(),
+              dayjs(gridSummary.max_end_date).toISOString(),
             ],
             y: gridSummary.task_id,
           };
@@ -177,17 +174,14 @@ export const Gantt = ({ limit, runType, triggeringUser }: 
Props) => {
 
           if (taskInstance) {
             const hasTaskRunning = isStatePending(taskInstance.state);
-            const endTime = hasTaskRunning ? currentTime : 
taskInstance.end_date;
+            const endTime = hasTaskRunning ? dayjs().toISOString() : 
taskInstance.end_date;
 
             return {
               isGroup: node.isGroup,
               isMapped: node.is_mapped,
               state: taskInstance.state,
               taskId: taskInstance.task_id,
-              x: [
-                formatDate(taskInstance.start_date, selectedTimezone, 
DEFAULT_DATETIME_FORMAT_WITH_TZ),
-                formatDate(endTime, selectedTimezone, 
DEFAULT_DATETIME_FORMAT_WITH_TZ),
-              ],
+              x: [dayjs(taskInstance.start_date).toISOString(), 
dayjs(endTime).toISOString()],
               y: taskInstance.task_id,
             };
           }
@@ -196,7 +190,7 @@ export const Gantt = ({ limit, runType, triggeringUser }: 
Props) => {
         return undefined;
       })
       .filter((item) => item !== undefined);
-  }, [flatNodes, gridTiSummaries, taskInstancesData, selectedTimezone, 
isLoading, runId, currentTime]);
+  }, [flatNodes, gridTiSummaries, taskInstancesData, isLoading, runId]);
 
   // Get all unique states and their colors
   const states = [...new Set(data.map((item) => item.state ?? "none"))];

Reply via email to