Worktime#
The working time of one calendar: daily hours, working weekdays and per-date exceptions. It's the Worktime property of CalendarData. Create it with new Worktime() and an object initializer. A Worktime with no properties set is the built-in schedule: Monday-Friday, 08:00-12:00 and 13:00-17:00.
This page also documents TimeRange and DayRule, the types its properties hold.
Declaration#
public sealed class Worktime : IDeepCloneable<Worktime>
Properties#
| Property | Type | Default | Description |
|---|---|---|---|
Hours |
List<TimeRange>? |
null = 08:00-12:00, 13:00-17:00 |
Working hours of every working weekday. |
Days |
bool[]? |
null = Monday-Friday |
Working weekdays, exactly 7 entries. |
Dates |
SortedDictionary<Moment, DayRule> |
empty | Date exceptions. An entry replaces the weekday rule for that date. |
Hours#
public List<TimeRange>? Hours { get; set; }
Each TimeRange is one working interval of the day. All working weekdays share these hours. The order of the ranges doesn't matter. An empty list means no working hours on any weekday, so only Dates entries can add working time.
Days#
public bool[]? Days { get; set; }
Index 0 is Sunday, index 6 is Saturday. true marks a working day. A weekday marked false has no working time unless a Dates entry overrides it.
Dates#
public SortedDictionary<Moment, DayRule> Dates { get; set; }
Per-date overrides. The DayRule for a date wins over Days and Hours. The key is a Moment, but only its date counts, so use the date's midnight. Two keys on the same date don't raise an error: the later one replaces the earlier one.
Methods#
DeepClone#
public Worktime DeepClone()
Returns a copy that shares no list, array or DayRule with this one.
Worktime doesn't implement IEquatable<Worktime>, so Equals compares references.
Validation#
Worktime is checked when the project data is loaded. Invalid values throw InputException with one of these paths:
| Problem | Path |
|---|---|
Days doesn't have exactly 7 entries |
calendars[i].worktime.days |
A range in Hours is outside 00:00-24:00 |
calendars[i].worktime.hours |
A range in a DayRule.Hours entry is outside 00:00-24:00 |
calendars[i].worktime.dates[YYYY-MM-DD] |
A calendar whose worktime adds up to no working time at all is rejected too; see CalendarData.
TimeRange#
One working interval of a day, in minutes from midnight.
public record struct TimeRange(ushort Start, ushort End)
| Property | Type | Description |
|---|---|---|
Start |
ushort |
Start minute, 0-1439. |
End |
ushort |
End minute, up to 1440 (24:00). When End <= Start, the range crosses midnight and belongs to the day it starts on. |
new TimeRange(9 * 60, 18 * 60) is 09:00-18:00. new TimeRange(22 * 60, 6 * 60) is a night shift from 22:00 to 06:00 the next morning.
DayRule#
The working time of one date in Dates. On that date the rule replaces the weekday rule, in both directions: it can turn a working weekday off or a weekend day on.
public abstract record DayRule : IDeepCloneable<DayRule>
{
public sealed record Off : DayRule;
public sealed record On : DayRule;
public sealed record Hours(List<TimeRange> Ranges) : DayRule;
public abstract DayRule DeepClone();
}
The set of variants is closed: the constructor is private, so only these three exist.
| Variant | Description |
|---|---|
DayRule.Off |
Non-working date, such as a holiday. |
DayRule.On |
Working date with the calendar's regular Hours. |
DayRule.Hours(List<TimeRange> Ranges) |
Working date with these ranges instead of the regular hours. An empty list works like Off. |
DeepClone() returns a rule with its own copy of Ranges. Equality of two DayRule.Hours values compares the Ranges lists by reference, not by content.
Example#
using Plen;
static Moment Day(int year, int month, int day) =>
Moment.FromYmdHm(year, month, day, 0, 0) ?? throw new ArgumentException("invalid date");
var calendar = new CalendarData
{
Id = "office",
Worktime = new Worktime
{
// 09:00-18:00, minutes from midnight.
Hours = [new TimeRange(9 * 60, 18 * 60)],
// Sunday..Saturday: Monday-Friday.
Days = [false, true, true, true, true, true, false],
Dates =
{
// Public holiday.
[Day(2026, 12, 25)] = new DayRule.Off(),
// Short working Saturday, 09:00-13:00.
[Day(2026, 12, 19)] = new DayRule.Hours([new TimeRange(9 * 60, 13 * 60)]),
},
},
};
Console.WriteLine(calendar);
Related#
CalendarData- the calendar that holds the working timeMoment- the key of date exceptions- Working time and calendars - hours, weekdays and holidays