diff --git a/airflow-core/src/airflow/ui/src/components/DateTimeInput.test.tsx b/airflow-core/src/airflow/ui/src/components/DateTimeInput.test.tsx
new file mode 100644
index 0000000000000..170e6c64f09a7
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/components/DateTimeInput.test.tsx
@@ -0,0 +1,134 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { fireEvent, render, screen } from "@testing-library/react";
+import { describe, it, expect, vi } from "vitest";
+
+import { TimezoneContext } from "src/context/timezone";
+import { Wrapper } from "src/utils/Wrapper";
+
+import { DateTimeInput } from "./DateTimeInput";
+
+describe("DateTimeInput paste", () => {
+ it("Pastes a valid datetime and fires onChange with UTC value", () => {
+ const onChange = vi.fn();
+
+ render(
+
+
+ ,
+ { wrapper: Wrapper },
+ );
+
+ const input = screen.getByTestId("datetime-input");
+ const pasteEvent = new ClipboardEvent("paste", {
+ clipboardData: new DataTransfer(),
+ });
+ Object.defineProperty(pasteEvent, "clipboardData", {
+ value: {
+ getData: vi.fn().mockReturnValue("2026-05-13 10:00:00"),
+ },
+ });
+
+ fireEvent(input, pasteEvent);
+
+ expect(onChange).toHaveBeenCalledTimes(1);
+ const callArg = onChange.mock.calls[0][0];
+ expect(callArg.target.value).toBe("2026-05-13T10:00:00.000Z");
+ });
+
+ it("Interprets timezone-less pasted values in the selected timezone", () => {
+ const onChange = vi.fn();
+
+ render(
+
+
+ ,
+ { wrapper: Wrapper },
+ );
+
+ const input = screen.getByTestId("datetime-input");
+ const pasteEvent = new ClipboardEvent("paste", {
+ clipboardData: new DataTransfer(),
+ });
+ Object.defineProperty(pasteEvent, "clipboardData", {
+ value: {
+ getData: vi.fn().mockReturnValue("2026-05-13 10:00:00"),
+ },
+ });
+
+ fireEvent(input, pasteEvent);
+
+ expect(onChange).toHaveBeenCalledTimes(1);
+ const callArg = onChange.mock.calls[0][0];
+ // 10:00 in New York (EDT, UTC-4) → 14:00 UTC
+ expect(callArg.target.value).toBe("2026-05-13T14:00:00.000Z");
+ });
+
+ it("Does not fire onChange for an invalid pasted string", () => {
+ const onChange = vi.fn();
+
+ render(
+
+
+ ,
+ { wrapper: Wrapper },
+ );
+
+ const input = screen.getByTestId("datetime-input");
+ const pasteEvent = new ClipboardEvent("paste", {
+ clipboardData: new DataTransfer(),
+ });
+ Object.defineProperty(pasteEvent, "clipboardData", {
+ value: {
+ getData: vi.fn().mockReturnValue("not a date"),
+ },
+ });
+
+ fireEvent(input, pasteEvent);
+
+ expect(onChange).not.toHaveBeenCalled();
+ });
+
+ it("Does not fire onChange for an empty pasted string", () => {
+ const onChange = vi.fn();
+
+ render(
+
+
+ ,
+ { wrapper: Wrapper },
+ );
+
+ const input = screen.getByTestId("datetime-input");
+ const pasteEvent = new ClipboardEvent("paste", {
+ clipboardData: new DataTransfer(),
+ });
+ Object.defineProperty(pasteEvent, "clipboardData", {
+ value: {
+ getData: vi.fn().mockReturnValue(""),
+ },
+ });
+
+ fireEvent(input, pasteEvent);
+
+ expect(onChange).not.toHaveBeenCalled();
+ });
+});
diff --git a/airflow-core/src/airflow/ui/src/components/DateTimeInput.tsx b/airflow-core/src/airflow/ui/src/components/DateTimeInput.tsx
index add6addb8ddc8..d67c889efe3ad 100644
--- a/airflow-core/src/airflow/ui/src/components/DateTimeInput.tsx
+++ b/airflow-core/src/airflow/ui/src/components/DateTimeInput.tsx
@@ -19,7 +19,7 @@
import { Input, type InputProps } from "@chakra-ui/react";
import dayjs from "dayjs";
import tz from "dayjs/plugin/timezone";
-import { forwardRef, type ChangeEvent, useState } from "react";
+import { forwardRef, type ChangeEvent, type ClipboardEvent, useState } from "react";
import { useDebouncedCallback } from "use-debounce";
import { useTimezone } from "src/context/timezone";
@@ -54,9 +54,22 @@ export const DateTimeInput = forwardRef(({ onChange, va
debounceDelay,
);
+ const onPaste = (event: ClipboardEvent) => {
+ const pasted = event.clipboardData.getData("text");
+ if (!pasted) return;
+ const parsed = dayjs.tz(pasted, selectedTimezone);
+ if (!parsed.isValid()) return;
+ event.preventDefault();
+ const local = parsed.tz(selectedTimezone).format(DEFAULT_DATETIME_FORMAT);
+ const utc = parsed.toISOString();
+ setDisplayDate(local);
+ onChange?.({ ...event, target: { ...event.target, value: utc } } as unknown as ChangeEvent);
+ };
+
return (
{
const local = dayjs(event.target.value).isValid() ? event.target.value : "";