pyzo-ryzo opened a new issue, #67477:
URL: https://github.com/apache/airflow/issues/67477

   ### Under which category would you file this issue?
   
   Airflow Core
   
   ### Apache Airflow version
   
   3.2.1
   
   ### What happened and how to reproduce it?
   
   The Calendar view on the DAG detail page does not respect the user's 
selected timezone from the UI timezone selector. All dates — both in the API 
query parameters and in the rendered calendar grid — are computed using either 
browser-local time or hardcoded UTC, while the rest of the UI (e.g. the "Start 
Date" column on the Runs tab) correctly converts timestamps to the 
user-selected timezone.
    
   **Observed behavior:** Changing the timezone via the UI timezone selector 
has no effect on the Calendar view. Runs are grouped into the wrong day/hour 
cells for users whose selected timezone differs from UTC.
    
   **Comparison with Runs tab:** On the Runs tab, the `Start Date` column 
properly updates when the user changes their timezone setting, confirming the 
timezone selector itself works correctly.
   
   ## How to reproduce
    
   1. Set your Airflow UI timezone to something significantly offset from UTC 
(e.g. `Asia/Tokyo` — UTC+9, or `America/Los_Angeles` — UTC-7).
   2. Navigate to a DAG that has runs near midnight UTC.
   3. Open the **Calendar** tab → observe that runs are grouped by their UTC 
date/hour, not by the selected timezone.
   4. Switch to the **Runs** tab → observe that the `Start Date` column 
correctly shows times in the selected timezone.
   ## Root cause analysis
    
   The entire Calendar feature tree (`Calendar.tsx`, `calendarUtils.ts`, 
`HourlyCalendarView.tsx`, `DailyCalendarView.tsx`) was written using plain 
`dayjs()` without any awareness of the `useTimezone()` / `TimezoneContext` 
system that the rest of the Airflow UI uses. The `dayjs/plugin/timezone` and 
`dayjs/plugin/utc` plugins are not even imported in any of these files.
    
   There are three specific problem areas:
    
   ### 1. `Calendar.tsx` — API query dates hardcode a literal "Z" suffix
    
   ```typescript
   // Current code (Calendar.tsx)
   const gte = startDate.format("YYYY-MM-DD[T]HH:mm:ss[Z]");
   const lte = endDate.format("YYYY-MM-DD[T]HH:mm:ss[Z]");
   ```
    
   `[Z]` in a dayjs format string is a **literal character escape** — it 
unconditionally appends the letter `Z` (meaning "UTC") to whatever the 
browser-local time value is. This tells the API the timestamp is UTC when it is 
not. The component never calls `useTimezone()`.
    
   Compare with the `Time` component (used by the Runs tab), which correctly 
does:
    
   ```typescript
   // Time.tsx — correct pattern
   const { selectedTimezone } = useTimezone();
   const formattedTime = time.tz(selectedTimezone).format(format);
   ```
    
   ### 2. `calendarUtils.ts` — Run grouping uses raw UTC string slicing
    
   ```typescript
   // createDailyDataMap
   const dateStr = run.date.slice(0, 10);  // "YYYY-MM-DD" — always UTC
    
   // createHourlyDataMap
   const hourStr = run.date.slice(0, 13);  // "YYYY-MM-DDTHH" — always UTC
   ```
    
   If the API returns a UTC timestamp like `2024-01-15T23:30:00Z`, this groups 
the run into January 15. But for a user in `Asia/Tokyo` (UTC+9), that run 
occurred on January 16 at 08:30 and should appear in that day's cell.
    
   The `generateDailyCalendarData` and `generateHourlyCalendarData` functions 
also build their calendar grids using plain `dayjs()` (browser-local), with no 
timezone parameter.
    
   ### 3. `HourlyCalendarView.tsx` / `DailyCalendarView.tsx` — Display 
formatting uses plain dayjs
    
   Both views format display labels (day number, weekday name, month 
abbreviation) with plain `dayjs(day.day)` calls that don't go through timezone 
conversion.
    
   ## Suggested fix
    
   Thread `selectedTimezone` from the `useTimezone()` hook through the 
component tree:
    
   - **`Calendar.tsx`**: Import `useTimezone`, compute the date range in the 
selected timezone, convert to UTC for the API query.
   - **`calendarUtils.ts`**: Add a `timezone` parameter to 
`createDailyDataMap`, `createHourlyDataMap`, `generateDailyCalendarData`, 
`generateHourlyCalendarData`, and `calculateDataBounds`. Use 
`dayjs(run.date).tz(timezone)` instead of string slicing for grouping.
   - **Views**: Pass the timezone through and use it for display formatting.
   This follows the same pattern already established by 
`src/components/Time.tsx` and `src/utils/datetimeUtils.ts`.
    
   ### Affected files
    
   - `airflow-core/src/airflow/ui/src/pages/Dag/Calendar/Calendar.tsx`
   - `airflow-core/src/airflow/ui/src/pages/Dag/Calendar/calendarUtils.ts`
   - `airflow-core/src/airflow/ui/src/pages/Dag/Calendar/HourlyCalendarView.tsx`
   - `airflow-core/src/airflow/ui/src/pages/Dag/Calendar/DailyCalendarView.tsx`
   
   ### What you think should happen instead?
   
   The Calendar view should respect the user-selected timezone (from 
`useTimezone()` / `TimezoneContext`) consistently with the rest of the UI. 
Specifically:
    
   1. The date range sent to the API should be computed in the selected 
timezone and then converted to UTC.
   2. Runs should be grouped into day/hour buckets based on the selected 
timezone, not by raw UTC string slicing.
   3. Display labels (day numbers, weekday names, month headers) should reflect 
the selected timezone.
   
   
   ### Operating System
   
   Red Hat Enterprise Linux 9.7
   
   ### Deployment
   
   Virtualenv installation
   
   ### Apache Airflow Provider(s)
   
   _No response_
   
   ### Versions of Apache Airflow Providers
   
   _No response_
   
   ### Official Helm Chart version
   
   Not Applicable
   
   ### Kubernetes Version
   
   Not Applicable
   
   ### Helm Chart configuration
   
   Not Applicable
   
   ### Docker Image customizations
   
   _No response_
   
   ### Anything else?
   
   The `CalendarCell.tsx` tooltip display may also need updating if it shows 
raw date strings, but the four files listed above are the core of the issue.
   
   
   ### Are you willing to submit PR?
   
   - [x] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to