Worktime#

The working time of a calendar: daily hours, working weekdays and per-date exceptions. It's set as CalendarData.worktime. Create one with new Worktime() and set fields with the fluent withX setters. A field left at null keeps its built-in default.

Declaration#

public class Worktime extends ValueRecord implements DeepCloneable<Worktime>

The engine validates a Worktime when the data is passed to Project#solve(data, …) or Engine.schedule. Invalid values throw an unchecked InputException whose path starts with calendars[i].worktime.

Constructors#

Worktime()#

public Worktime()

Creates a worktime with every field at its default: hours and days are null, dates is an empty map.

Fields#

hours#

public Vec<TimeRange> hours = null;

The working ranges of a regular working day, as TimeRange values. null means 08:00-12:00 and 13:00-17:00. An empty list means no working hours on regular days. Ranges don't have to be sorted.

Throws InputException at calendars[i].worktime.hours when a range is outside 00:00-24:00.

days#

public boolean[] days = null;

Which weekdays are working days, one flag per day. Index 0 is Sunday, index 6 is Saturday. null means Monday to Friday.

Throws InputException at calendars[i].worktime.days when the array doesn't have exactly 7 entries.

dates#

public SortedDict<Moment, DayRule> dates = new SortedDict<Moment, DayRule>();

Date exceptions: a DayRule per date, applied instead of hours and days on that date. A rule can make a weekend date working or a weekday off. Default: an empty SortedDict, which you can fill in place with dates.put(...). Must not be null.

Only the date part of the Moment key counts. Use the date's midnight as the key. Two keys on the same date collide: the rule with the later Moment replaces the other, without an error.

A worktime whose hours, days and dates give no working time at all throws InputException at calendars[i] (calendar has no working time).

Methods#

withHours#

public Worktime withHours(Vec<TimeRange> value)
public Worktime withHours(java.util.Collection<? extends TimeRange> value)

Sets hours and returns this instance. The Collection overload copies the items into a new Vec, so List.of(...) works. null restores the default hours.

Parameters

Name Type Description
value Vec<TimeRange> or Collection<? extends TimeRange> The working ranges, or null

Returns - this Worktime.

withDays#

public Worktime withDays(boolean[] value)

Sets days and returns this instance. The array is stored as given, not copied. null restores Monday to Friday.

Parameters

Name Type Description
value boolean[] Seven flags, Sunday first, or null

Returns - this Worktime.

withDates#

public Worktime withDates(SortedDict<Moment, DayRule> value)

Sets dates and returns this instance. The map is stored as given, not copied.

Parameters

Name Type Description
value SortedDict<Moment, DayRule> The date exceptions; not null

Returns - this Worktime.

deepClone#

public Worktime deepClone()

Returns a copy that shares no list, array or map with this instance. Each TimeRange and DayRule is copied too.

Returns - a new Worktime equal to this one.

copy#

public Worktime copy()

Returns a shallow copy. The copy shares the hours list, the days array and the dates map with this instance.

Returns - a new Worktime with the same field references.

equals, hashCode, toString#

public boolean equals(Object other)
public int hashCode()
public String toString()

Inherited from ValueRecord. Two Worktime values are equal when hours, days (by content) and dates are equal.

TimeRange#

A working range within one day, in minutes since midnight.

public class TimeRange extends ValueRecord
Member Type Description
TimeRange(int start, int end) constructor Creates a range from start to end
start int Start, in minutes since midnight. Must be below 1440
end int End, in minutes since midnight, up to 1440 (24:00)
copy() TimeRange Returns a copy with the same values

A range with end less than or equal to start crosses midnight and belongs to the day it starts on: new TimeRange(22 * 60, 6 * 60) is 22:00 to 06:00 the next morning. Equal start and end give a 24-hour range.

DayRule#

The rule for one date in dates. DayRule is an abstract class with a closed set of nested subclasses. Match on them with instanceof or a switch pattern.

public abstract class DayRule extends ValueRecord implements DeepCloneable<DayRule>
Subclass Constructor Effect on the date
DayRule.Off new DayRule.Off() Non-working
DayRule.On new DayRule.On() Working, with the worktime's hours
DayRule.Hours new DayRule.Hours(Vec<TimeRange> ranges), new DayRule.Hours(Collection<? extends TimeRange> ranges) Working, with these ranges instead of hours; field ranges (Vec<TimeRange>)

DayRule.Hours ranges follow the same rules as TimeRange. A range outside 00:00-24:00 throws InputException at calendars[i].worktime.dates[YYYY-MM-DD].

Method Returns Description
deepClone() DayRule A copy that shares no list with this rule. Off and On hold no data and return themselves
copy() the subclass A shallow copy

Example#

import org.dhtmlx.plen.*;
import java.util.List;

public class ShiftCalendar {
    public static void main(String[] args) throws Exception {
        Moment holiday = Moment.fromYmdHm(2026, 8, 14, 0, 0);  // Friday
        Moment saturday = Moment.fromYmdHm(2026, 8, 15, 0, 0);
        Moment start = Moment.fromYmdHm(2026, 8, 13, 7, 0);    // Thursday

        Worktime worktime = new Worktime()
            .withHours(List.of(new TimeRange(7 * 60, 11 * 60), new TimeRange(12 * 60, 16 * 60)))
            .withDays(new boolean[] {false, true, true, true, true, true, false}); // Sun..Sat
        worktime.dates.put(holiday, new DayRule.Off());
        worktime.dates.put(saturday, new DayRule.Hours(List.of(new TimeRange(8 * 60, 12 * 60))));

        ProjectData data = new ProjectData()
            .withConfig(new SchedulingConfig().withDurationUnit(TimeUnit.HOUR))
            .withCalendars(List.of(new CalendarData().withId(Id.str("global")).withWorktime(worktime)))
            .withTasks(List.of(new TaskData(Id.str("pour")).withStartDate(start).withDuration(14.0)));

        ScheduleResult result = Engine.schedule(data, new SolveOptions().withIncludeUnchanged(true));
        for (Mutation update : result.updates) {
            System.out.println(update.id + ": " + update.startDate + " -> " + update.endDate);
        }
    }
}

Output:

pour: 2026-08-13 07:00 -> 2026-08-17 09:00

The 14 hours are Thursday (8 h), Saturday (4 h) and Monday 07:00-09:00 (2 h). Friday is off. For how tasks and resources pick a calendar, see Working time and calendars.