---
title: "React Timeline 36-Hour Rolling Window Schedule Example | Mobiscroll"
component: "Timeline"
framework: "React"
library_version: "6.1.5"
url: "https://demo.mobiscroll.com/react/timeline/36-hour-rolling-window-aircraft-view"
---

# 36-Hour Rolling Window Schedule - React Timeline demo

Build a fleet scheduling view on the React Timeline — a 36-hour rolling window that auto-advances from the current hour. For React and Next.JS.

- [Live demo](https://demo.mobiscroll.com/react/timeline/36-hour-rolling-window-aircraft-view)
- [View React JS code on GitHub](https://github.com/acidb/mobiscroll-demos-react/tree/main/src/demos/eventcalendar/timeline/36-hour-rolling-window-aircraft-view)
- [View React TS code on GitHub](https://github.com/acidb/mobiscroll-demos-react-ts/tree/main/src/demos/eventcalendar/timeline/36-hour-rolling-window-aircraft-view)
- This demo in other frameworks: [JavaScript](https://demo.mobiscroll.com/javascript/timeline/36-hour-rolling-window-aircraft-view.md), [jQuery](https://demo.mobiscroll.com/jquery/timeline/36-hour-rolling-window-aircraft-view.md), [Angular](https://demo.mobiscroll.com/angular/timeline/36-hour-rolling-window-aircraft-view.md), [Vue](https://demo.mobiscroll.com/vue/timeline/36-hour-rolling-window-aircraft-view.md)

## Description

The timeline component is ideal for highly dynamic resource management scenarios, such as tracking a global aircraft fleet, offering a powerful visualization solution. The primary technical focus is on creating a 36-hour continuous, forward-looking window that automatically updates to start from the current hour, providing an adaptive "rolling" schedule view.

To implement the dynamic 36-hour window, a single-day [`timeline view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) is configured. The `startTime` and `endTime` properties are calculated in JavaScript based on the current system time prior to initialization. This calculation ensures the view always spans exactly 36 hours ahead, which is achieved by setting the `endTime` with a calculated date offset (e.g., +1 or +2 days) to leverage the shifted days feature for continuous rendering. The time axis resolution is hourly, which is optimal for monitoring time-sensitive flights and maintenance events.

The [resources](https://mobiscroll.com/docs/react/eventcalendar/api#opt-resources), representing individual aircraft (tail numbers), are organized in a hierarchical structure (e.g., Airbus A350-900/Base: LAX → N351AD). This grouping allows managers to quickly drill down from a fleet level to an individual aircraft's current status. [Events](https://mobiscroll.com/docs/react/eventcalendar/api#opt-data), which represent flights, are labeled concisely with common IATA airport codes (e.g., "JFK → LHR") for immediate route identification.

## What this demo shows

- A desktop timeline configured as a 36-hour rolling window for aircraft scheduling.
- **Timeline layout** Displays time horizontally and aircraft resources vertically, with a hierarchical resource tree on the left.
- **Resource grouping** Organizes aircraft under aircraft model and base airport combinations, such as A330-200 / DXB, A330-300 / JFK, and A350-900 / HND.
- **Aircraft resources** Shows individual aircraft registrations as child resources within each aircraft group.
- **Flight assignments** Places flight events on the timeline by assigned aircraft, date, start time, and end time.
- **Flight details** Displays flight cards with origin and destination airport codes, departure time, and arrival time.
- **Multiple legs** Shows multiple flight legs assigned to the same aircraft within the visible scheduling window.
- **Overnight flights** Includes flights that continue across the day boundary into the following date.
- **Event styling** Uses different event colors to distinguish flight assignments or aircraft schedules.
- **UTC display** Shows the schedule in UTC, with a resource-header label indicating that times are shown in UTC.
- **Current time** Displays a current time indicator as a vertical blue line with a time label.
- **Hover behavior** Shows a time indicator over the grid that follows the cursor in 15-minute increments.
- **Expandable groups** Supports expanding and collapsing aircraft groups to make larger fleets easier to navigate.
- **Scrolling behavior** Supports horizontal and vertical scrolling for working across many aircraft and time periods.
- **Event interaction** Highlights events on hover and exposes drag and resize handles for moving events or changing their duration.
- **Event selection** Selects and highlights an event when it is clicked.

## Best for

- **Airline operations** Managing flight assignments across multiple aircraft in a single timeline.
- **Aircraft scheduling** Planning aircraft usage by tail number, aircraft model, and base airport.
- **Fleet management** Reviewing grouped aircraft schedules while still allowing drill-down to individual registrations.
- **Flight planning** Coordinating multiple flight legs, overnight flights, and long-haul routes across a forward-looking time window.
- **Operations control rooms** Monitoring time-sensitive aircraft activity in a UTC-based view.
- **Large resource sets** Navigating schedules that require hierarchical grouping, expandable resource rows, and both horizontal and vertical scrolling.

## API used in this demo

- [`theme`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-theme) - option
- [`themeVariant`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-themeVariant) - option
- [`cssClass`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-cssClass) - option
- [`data`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-data) - option
- [`dataTimezone`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-dataTimezone) - option
- [`displayTimezone`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-displayTimezone) - option
- [`view`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-view) - option
- [`resources`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-resources) - option
- [`showControls`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-showControls) - option
- [`renderResourceHeader`](https://mobiscroll.com/docs/react/eventcalendar/api#renderer-renderResourceHeader) - renderer
- [`timezonePlugin`](https://mobiscroll.com/docs/react/eventcalendar/api#opt-timezonePlugin) - option

## Code

### JSX

```jsx
import { dayjsTimezone, Eventcalendar, setOptions } from '@mobiscroll/react';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { useCallback, useMemo } from 'react';

dayjs.extend(utc);

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

function App() {
  const startTime = useMemo(() => dayjs.utc().format('HH:00'), []);

  const endTime = useMemo(() => {
    const start = dayjs.utc().startOf('hour');
    const end = start.add(36, 'hours');
    const dayOffset = end.subtract(1, 'minute').startOf('day').diff(start.startOf('day'), 'days');
    const suffix = dayOffset > 0 ? '+' + dayOffset : '';
    return end.format('HH:00') + suffix;
  }, []);

  const myEvents = useMemo(
    () => [
      {
        resource: '1-1',
        title: 'DXB → BKK',
        start: '2026-10-27T08:30',
        end: '2026-10-27T14:45',
        color: '#22c55e',
      },
      {
        resource: '1-1',
        title: 'BKK → SIN',
        start: '2026-10-27T20:30',
        end: '2026-10-27T23:00',
        color: '#22c55e',
      },
      {
        resource: '1-1',
        title: 'SIN → CDG',
        start: '2026-10-28T04:30',
        end: '2026-10-28T15:00',
        color: '#22c55e',
      },
      {
        resource: '1-1',
        title: 'CDG → GVA',
        start: '2026-10-28T21:30',
        end: '2026-10-28T22:45',
        color: '#22c55e',
      },
      {
        resource: '1-2',
        title: 'JFK → AMS',
        start: '2026-10-27T21:00',
        end: '2026-10-28T08:30',
        color: '#3b82f6',
      },
      // Showing partial data. Download full source.
    ],
    [],
  );

  const myResources = useMemo(
    () => [
      {
        id: '1',
        name: 'A330-200 / DXB',
        eventCreation: false,
        children: [
          {
            id: '1-1',
            name: 'A6-ECC',
          },
          {
            id: '1-2',
            name: 'A6-AFA',
          },
          {
            id: '1-3',
            name: 'A6-DHB',
          },
        ],
      },
      {
        id: '2',
        name: 'A330-300 / JFK',
        eventCreation: false,
        children: [
          {
            id: '2-1',
            name: 'N733AL',
          },
          {
            id: '2-2',
            name: 'N338UA',
          },
          {
            id: '2-3',
            name: 'N412NY',
          },
        ],
      },
      // Showing partial data. Download full source.
    ],
    [],
  );

  const myView = useMemo(
    () => ({
      timeline: {
        type: 'day',
        startTime,
        endTime,
      },
    }),
    [startTime, endTime],
  );

  const customResourceHeader = useCallback(
    () => (
      <div className="mds-36-hour-resource-header">
        TIMES SHOWN IN <span className="mds-36-hour-resource-header-utc">UTC</span>
      </div>
    ),
    [],
  );

  return (
    <Eventcalendar
      cssClass="mds-36-hour-rolling-calendar"
      data={myEvents}
      dataTimezone="utc"
      displayTimezone="utc"
      view={myView}
      resources={myResources}
      showControls={false}
      renderResourceHeader={customResourceHeader}
      timezonePlugin={dayjsTimezone}
    />
  );
}

export default App;
```

### TSX

```tsx
import {
  dayjsTimezone,
  Eventcalendar,
  MbscCalendarEvent,
  MbscEventcalendarView,
  MbscResource,
  setOptions,
} from '@mobiscroll/react';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import { FC, useCallback, useMemo } from 'react';

dayjs.extend(utc);

setOptions({
  theme: 'ios',
  themeVariant: 'light'
});

const App: FC = () => {
  const startTime = useMemo(() => dayjs.utc().format('HH:00'), []);

  const endTime = useMemo(() => {
    const start = dayjs.utc().startOf('hour');
    const end = start.add(36, 'hours');
    const dayOffset = end.subtract(1, 'minute').startOf('day').diff(start.startOf('day'), 'days');
    const suffix = dayOffset > 0 ? '+' + dayOffset : '';
    return end.format('HH:00') + suffix;
  }, []);

  const myEvents: MbscCalendarEvent[] = useMemo(
    () => [
      {
        resource: '1-1',
        title: 'DXB → BKK',
        start: '2026-10-27T08:30',
        end: '2026-10-27T14:45',
        color: '#22c55e',
      },
      {
        resource: '1-1',
        title: 'BKK → SIN',
        start: '2026-10-27T20:30',
        end: '2026-10-27T23:00',
        color: '#22c55e',
      },
      {
        resource: '1-1',
        title: 'SIN → CDG',
        start: '2026-10-28T04:30',
        end: '2026-10-28T15:00',
        color: '#22c55e',
      },
      {
        resource: '1-1',
        title: 'CDG → GVA',
        start: '2026-10-28T21:30',
        end: '2026-10-28T22:45',
        color: '#22c55e',
      },
      {
        resource: '1-2',
        title: 'JFK → AMS',
        start: '2026-10-27T21:00',
        end: '2026-10-28T08:30',
        color: '#3b82f6',
      },
      // Showing partial data. Download full source.
    ],
    [],
  );

  const myResources: MbscResource[] = useMemo(
    () => [
      {
        id: '1',
        name: 'A330-200 / DXB',
        eventCreation: false,
        children: [
          {
            id: '1-1',
            name: 'A6-ECC',
          },
          {
            id: '1-2',
            name: 'A6-AFA',
          },
          {
            id: '1-3',
            name: 'A6-DHB',
          },
        ],
      },
      {
        id: '2',
        name: 'A330-300 / JFK',
        eventCreation: false,
        children: [
          {
            id: '2-1',
            name: 'N733AL',
          },
          {
            id: '2-2',
            name: 'N338UA',
          },
          {
            id: '2-3',
            name: 'N412NY',
          },
        ],
      },
      // Showing partial data. Download full source.
    ],
    [],
  );

  const myView: MbscEventcalendarView = useMemo(
    () => ({
      timeline: {
        type: 'day',
        startTime,
        endTime,
      },
    }),
    [startTime, endTime],
  );

  const customResourceHeader = useCallback(
    () => (
      <div className="mds-36-hour-resource-header">
        TIMES SHOWN IN <span className="mds-36-hour-resource-header-utc">UTC</span>
      </div>
    ),
    [],
  );

  return (
    <Eventcalendar
      cssClass="mds-36-hour-rolling-calendar"
      data={myEvents}
      dataTimezone="utc"
      displayTimezone="utc"
      view={myView}
      resources={myResources}
      showControls={false}
      renderResourceHeader={customResourceHeader}
      timezonePlugin={dayjsTimezone}
    />
  );
};

export default App;
```

### CSS

```css
.mds-36-hour-rolling-calendar .mbsc-timeline-parent {
  height: 32px;
}

.mds-36-hour-rolling-calendar .mds-36-hour-resource-header {
  font-weight: 100;
}

.mds-36-hour-rolling-calendar .mds-36-hour-resource-header-utc {
  font-weight: bold;
}

.mds-36-hour-rolling-calendar .mds-36-hour-date {
  font-size: bold;
  color: #e74949ff;
}

.mds-36-hour-rolling-calendar .mds-36-hour-time {
  color: #877d7dff;
}
```

## Implementation notes

- Use `type: 'day'` with dynamically computed `startTime` and `endTime` (both in `useMemo` with empty deps) to create a 36-hour rolling window anchored to the current UTC hour.
- Compute `startTime` as `dayjs.utc().format('HH:00')`. Compute `endTime` by adding 36 hours to `dayjs.utc().startOf('hour')`, then appending a `'+N'` day-offset suffix when the window extends into a later calendar day - subtract 1 minute from the end before comparing dates to avoid counting exact midnight as the next day.
- Set `dataTimezone` and `displayTimezone` both to `'utc'` and pass the `dayjsTimezone` plugin to `timezonePlugin` so all timestamps are interpreted and displayed in UTC.
- Set `showControls={false}` - the view is always anchored to now and needs no date navigation.
- Define resources as a two-level tree: parent nodes encode aircraft model and home base (e.g., `"A350-900 / LAX"`) with `eventCreation: false`, and child leaf nodes carry individual tail number IDs.
- Label each event with IATA airport codes in `"ORIG → DEST"` format and assign a `color` per aircraft family.
- Use `renderResourceHeader` (Angular: `resourceHeaderTemplate`, Vue: `#resourceHeader` slot) to render a static `"TIMES SHOWN IN UTC"` label in the resource column header.

## Run it in your project

1. If not signed up yet, or don't own a license, you can [start a free trial](https://mobiscroll.com/starttrial).

2. Clone the repository:

   ```
   git clone https://github.com/acidb/mobiscroll-demos-react.git
   ```

3. If not installed yet, install the Mobiscroll CLI from NPM:

   ```
   npm install -g @mobiscroll/cli
   ```

4. Config Mobiscroll - open a terminal window in the root directory and run:

   ```
   mobiscroll config react
   ```

5. Install dependencies - open a terminal window in the root directory and run:

   ```
   npm install
   ```

6. Run the project:

   ```
   npm run dev
   ```

On a trial, add `--trial` to the config command: `mobiscroll config react --trial`.

Running a demo locally requires a Mobiscroll trial or a license; setup is per framework at https://mobiscroll.com/docs/react/getting-started/installation

## Related demos

- Previous: [Event Grouping & Bulk Actions](https://demo.mobiscroll.com/react/timeline/event-grouping-bulk-action.md) - Group React Timeline events into collapsible client/quarter blocks and bulk-drag groups — switch between assignee and work-type views on a full-year layout.
- Next: [Drag People onto Events](https://demo.mobiscroll.com/react/timeline/drop-assignee-on-event-from-list.md) - Build a team assignment interface on a React Timeline — drag people from an external list onto booked meetings.
