[Canonical page](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-data/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# TaskData

One task, summary or milestone. Tasks go in [`ProjectData::tasks`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>); the same struct adds a task to a live project through [`SchedulingChanges::tasks`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/scheduling-changes.md>)`.add`. Build it with [`TaskData::new`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-data.md#new>) and struct update syntax, since `TaskData` doesn't implement `Default`.

## Declaration

```rust
#[derive(Clone, Debug)]
pub struct TaskData {
    pub id: Id,
    pub parent: Option<Id>,
    pub task_type: TaskType,
    pub start_date: Option<DateTime>,
    pub end_date: Option<DateTime>,
    pub duration: Option<f64>,
    pub duration_unit: Option<TimeUnit>,
    pub constraint_type: Option<ConstraintType>,
    pub constraint_date: Option<DateTime>,
    pub auto_scheduling: bool,
    pub unscheduled: bool,
    pub progress: f64,
    pub priority: u16,
    pub leveling_delay: f64,
    pub pauses: Vec<Pause>,
    pub calendar_id: Option<Id>,
}
```

## Constructors

### new

```rust
pub fn new(id: impl Into<Id>) -> TaskData
```

Creates a task with the given id and every other field at the default listed under [Fields](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-data.md#fields>). Accepts anything that converts into an [`Id`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id.md>): `1`, `"design"`, a `String`.

**Returns** a plain task ([`TaskType::Task`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-type.md>)) with no dates, no duration and automatic scheduling on.

## Fields

### id

```rust
pub id: Id
```

Task id, unique among the project's tasks.

### parent

```rust
pub parent: Option<Id>
```

Id of the parent task. `None`, `""` or a value equal to [`SchedulingConfig::root_id`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/scheduling-config.md#root_id>) means a top-level task.

Default: `None`.

### task_type

```rust
pub task_type: TaskType
```

Plain task, summary or milestone. Decides which date fields are needed, see [Dates by task type](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-data.md#dates-by-task-type>).

Default: `TaskType::Task`.

### start_date

```rust
pub start_date: Option<DateTime>
```

Start of the task.

Default: `None`.

### end_date

```rust
pub end_date: Option<DateTime>
```

End of the task. Must not be before `start_date`.

Default: `None`.

### duration

```rust
pub duration: Option<f64>
```

Working time in `duration_unit`. Finite and `>= 0`.

Default: `None`.

### duration_unit

```rust
pub duration_unit: Option<TimeUnit>
```

Unit of `duration`, `leveling_delay` and `pauses`. `None` uses [`SchedulingConfig::duration_unit`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/scheduling-config.md#duration_unit>).

Default: `None`.

### constraint_type

```rust
pub constraint_type: Option<ConstraintType>
```

Date constraint on the task. Takes effect only when [`SchedulingConfig::apply_constraints`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/scheduling-config.md#apply_constraints>) is `true`.

Default: `None`.

### constraint_date

```rust
pub constraint_date: Option<DateTime>
```

Date of the constraint. Required when `constraint_type` is a dated type (every type except `Asap` and `Alap`).

Default: `None`.

### auto_scheduling

```rust
pub auto_scheduling: bool
```

`false` fixes the task: the scheduler never moves it.

Default: `true`.

### unscheduled

```rust
pub unscheduled: bool
```

`true` leaves the task and all its descendants out of scheduling and out of results. Such tasks need no dates.

Default: `false`.

### progress

```rust
pub progress: f64
```

Completed share, from `0.0` to `1.0`. With [`SchedulingConfig::use_progress`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/scheduling-config.md#use_progress>), `1.0` marks the task completed and fixed.

Default: `0.0`.

### priority

```rust
pub priority: u16
```

Leveling priority, from `0` to `1000`. When leveling picks which task to delay, the lower priority gives way; `1000` is never leveled.

Default: `500`.

### leveling_delay

```rust
pub leveling_delay: f64
```

Elapsed time added before the task's driven start, in `duration_unit` (a day is 24 hours). Finite and `>= 0`. Written by [`Project::level`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#level>).

Default: `0.0`.

### pauses

```rust
pub pauses: Vec<Pause>
```

Splits in the task's work, sorted by `at` and non-overlapping. Written by [`Project::level`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#level>). Ignored on summaries, milestones and unscheduled tasks.

Default: empty.

### calendar_id

```rust
pub calendar_id: Option<Id>
```

Id of the task's working calendar. `None` uses the `"global"` calendar, or the nearest ancestor's calendar under [`CalendarMode::TaskInherited`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/calendar-mode.md>).

Default: `None`.

## Dates by task type

`start_date`, `end_date` and `duration` are read differently for each [`TaskType`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/task-type.md>). Unscheduled tasks skip these rules.

| Task type | Accepted input | Result |
|---|---|---|
| `Task` | `start_date` + `duration` | End computed forward on the task's calendar, around any `pauses`. |
| `Task` | `end_date` + `duration` | Start computed backward from the end. |
| `Task` | `start_date` + `end_date` | `duration` is the working time between the dates. |
| `Task` | all three | Accepted only when `start_date` + `duration` lands on `end_date`. |
| `Summary` | `start_date` + `end_date` | The given span. `duration` is ignored. |
| `Summary` | neither date | Span taken from the dated children. |
| `Milestone` | `start_date` or `end_date` | A zero-length task at that date. `duration` is ignored. |

A summary with only one of the two dates is an error, and so is a plain task with fewer than two of the three fields.

## Errors

Under the default [`Validation::Strict`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/validation.md>), an invalid task fails [`Project::solve`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#solve>), [`schedule`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule.md>) and [`Project::analyze`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#analyze>) with [`Error::Input`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>) at a path under `tasks[i]`:

| Path | When it occurs |
|---|---|
| `tasks[i].progress` | `progress` isn't finite or is outside `0.0..=1.0` |
| `tasks[i].priority` | `priority` is greater than `1000` |
| `tasks[i].leveling_delay` | `leveling_delay` isn't finite or is negative |
| `tasks[i].duration` | `duration` isn't finite or is negative; or all three date fields are set and disagree |
| `tasks[i].constraint_date` | a dated `constraint_type` has no `constraint_date` |
| `tasks[i].pauses[j]` | pause `j` breaks a [`Pause`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/pause.md>) rule |
| `tasks[i].calendar_id` | `calendar_id` names no calendar in [`ProjectData::calendars`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>) and isn't `"global"` |
| `tasks[i].start_date` | a plain task has fewer than two of `start_date`, `end_date`, `duration`; a summary has only one date; a milestone has no date |
| `tasks[i].end_date` | `end_date` is before `start_date` |
| `tasks[i]` | a summary has no dates and no dated children |

Rules across tasks (unique ids, known parent, no hierarchy cycle) are on [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md#validation>). [`Validation::Repair`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/validation.md>) fixes several of these cases instead of rejecting them.

## Example

A summary with two dated children, a milestone at the end, and a task with a "start no earlier than" constraint:

```rust
use plen_core::{
    schedule, ConstraintType, DateTime, ProjectData, SchedulingConfig, SolveOptions, TaskData,
    TaskType,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let monday = DateTime::from_ymd_hm(2026, 4, 6, 8, 0).ok_or("invalid date")?;
    let friday = DateTime::from_ymd_hm(2026, 4, 10, 8, 0).ok_or("invalid date")?;

    let data = ProjectData {
        config: SchedulingConfig {
            apply_constraints: true,
            ..Default::default()
        },
        tasks: vec![
            TaskData {
                task_type: TaskType::Summary,
                ..TaskData::new("phase")
            },
            TaskData {
                parent: Some("phase".into()),
                start_date: Some(monday),
                duration: Some(2.0),
                ..TaskData::new("design")
            },
            TaskData {
                parent: Some("phase".into()),
                start_date: Some(monday),
                duration: Some(3.0),
                constraint_type: Some(ConstraintType::Snet),
                constraint_date: Some(friday),
                ..TaskData::new("build")
            },
            TaskData {
                task_type: TaskType::Milestone,
                start_date: Some(friday),
                ..TaskData::new("release")
            },
        ],
        ..Default::default()
    };

    let result = schedule(data, &SolveOptions::default())?;
    for update in &result.updates {
        println!("{update:?}");
    }
    Ok(())
}
```

For how links, constraints and summaries move tasks, see [Links, constraints and summaries](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/links-constraints-summaries.md>).

## Related

- [`TaskUpdate`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/changes/task-update.md>) - edits an existing task in a live project
- [`Mutation`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/mutation.md>) - the computed dates a task gets back
- [`LinkData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/link-data.md>) - dependencies between tasks
- [Project data](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/project-data.md>) - building tasks in an input snapshot
- [Links, constraints and summaries](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/links-constraints-summaries.md>) - how links, constraints and summaries move tasks
