PrevUpHomeNext

Building the schedule

The whole schedule consists of multiple independent 'sub' schedules, each addressing different attributes of holidays.

We need 3 Halt schedules, plus 1 Restart schedule as follows.

Regular Annual holidays

  1. Martin Luther King, Jr. Day occurs on the 3rd Monday in January.
  2. George Washington’s Birthday occurs on the 3rd Monday in February.
  3. Memorial Day occurs on the 5th Monday in February.
  4. Labor Day occurs on the 1st Monday in September.
  5. Columbus Day occurs on the 2nd Monday in October.
  6. Thanksgiving Day occurs on the 4th Thursday in November.

These are the 6 holidays, which can be simply repeated every year. This schedule doesn't need to be fixed to a certain year.

XML fragment
<fds:schedules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fds="http://xml.firedaemon.com/scheduling/v3" xmlns:fd="http://xml.firedaemon.com">
    <schedule name="Annual US Federal Holidays" fd:fixed_duration_as="downtime">
        <interval xsi:type="fds:attributive_interval" granularity="year_interval" length="1" blueprint="fixed_subrange_duration">

            <onset name="Martin Luther King, Jr. Day"
                   minute="0" hour="4" month="0" weekday="0" first_dow="0" nth_kday_of_month="3"/>
            <onset minute="0" hour="4" month="0" weekday="0" first_dow="0" nth_kday_of_month="3"/>

            <onset name="George Washington’s Birthday"
                   minute="0" hour="4" month="1" weekday="0" first_dow="0" nth_kday_of_month="3"/>
            <onset minute="0" hour="4" month="1" weekday="0" first_dow="0" nth_kday_of_month="3"/>

            <onset name="Memorial Day"
                   minute="0" hour="4" month="1" weekday="0" first_dow="0" nth_kday_of_month="5"/>
            <onset minute="0" hour="4" month="1" weekday="0" first_dow="0" nth_kday_of_month="5"/>

            <onset name="Labor Day"
                   minute="0" hour="4" month="8" weekday="0" first_dow="0" nth_kday_of_month="1"/>
            <onset minute="0" hour="4" month="8" weekday="0" first_dow="0" nth_kday_of_month="1"/>

            <onset name="Columbus Day"
                   minute="0" hour="4" month="9" weekday="0" first_dow="0" nth_kday_of_month="2"/>
            <onset minute="0" hour="4" month="9" weekday="0" first_dow="0" nth_kday_of_month="2"/>

            <onset name="Thanksgiving Day"
                   minute="0" hour="4" month="10" weekday="3" first_dow="0" nth_kday_of_month="4"/>
            <onset minute="0" hour="4" month="10" weekday="3" first_dow="0" nth_kday_of_month="4"/>
        </interval>
    </schedule>
</fds:schedules>

Annual, Regular US Federal Holidays.xml

C++ fragment
using fixed_duration_as = timepiece_settings::fixed_duration_as;

interval_schedule_data sd1{year_interval, L"Regular Annual holidays"};
sd1.appdata = fixed_duration_as::inverse_fixed_duration;
sd1.blueprint = onset_series_blueprint::fixed_subrange_duration;
// 6 onset/completion pairs
sd1.cycle.resize(6 * 2);
sd1.cycle[0] = {0, 0, 4, 0, 0, 0, Monday, iso_sunday, 3};     // Martin Luther King, Jr. Day
sd1.cycle[1] = {0, 0, 4, 0, 0, 0, Monday, iso_sunday, 3};     //
sd1.cycle[2] = {0, 0, 4, 0, 1, 0, Monday, iso_sunday, 3};     // George Washington’s Birthday
sd1.cycle[3] = {0, 0, 4, 0, 1, 0, Monday, iso_sunday, 3};     //
sd1.cycle[4] = {0, 0, 4, 0, 4, 0, Monday, iso_sunday, 5};     // Memorial Day
sd1.cycle[5] = {0, 0, 4, 0, 4, 0, Monday, iso_sunday, 5};     //
sd1.cycle[6] = {0, 0, 4, 0, 8, 0, Monday, iso_sunday, 1};     // Labor Day
sd1.cycle[7] = {0, 0, 4, 0, 8, 0, Monday, iso_sunday, 1};     //
sd1.cycle[8] = {0, 0, 4, 0, 9, 0, Monday, iso_sunday, 2};     // Columbus Day
sd1.cycle[9] = {0, 0, 4, 0, 9, 0, Monday, iso_sunday, 2};     //
sd1.cycle[10] = {0, 0, 4, 0, 10, 0, Thursday, iso_sunday, 4}; // Thanksgiving Day
sd1.cycle[11] = {0, 0, 4, 0, 10, 0, Thursday, iso_sunday, 4}; //

Annual holidays on certain days

  1. New Year's Day occurs on the 1st of January.
  2. Juneteenth occurs on the 19th of June.
  3. Independence Day occurs on the 4th of July.
  4. Veterans Day occurs on the 11th of November.
  5. Christmas Day occurs on the 25th of December.

When a federal holiday falls on a Saturday, it is usually observed on the preceding Friday. When the holiday falls on a Sunday, it is usually observed on the following Monday.

Due to this rule, those days are observed potentially on different dates each year. synkronize's timepoint generator doesn't know about those special rules, hence it is necessary to fix the schedule to a certain year.

XML fragment
<schedule name="2023 US Federal Holidays" fd:fixed_duration_as="downtime">
    <activity_boundary from="2023-01-01T00:00:00" until="2024-01-01T00:00:00"/>
    <interval xsi:type="fds:attributive_interval" granularity="year_interval" length="1" blueprint="fixed_subrange_duration">

        <onset name="New Year's Day (Observed)"
               minute="0" hour="4" monthday="1" month="0"/>
        <onset minute="0" hour="4" monthday="1" month="0"/>

        <onset name="Juneteenth"
               minute="0" hour="4" monthday="18" month="5"/>
        <onset minute="0" hour="4" monthday="18" month="5"/>

        <onset name="Independence Day"
               minute="0" hour="4" monthday="3" month="6"/>
        <onset minute="0" hour="4" monthday="3" month="6"/>

        <onset name="Veterans Day (Observed)"
               minute="0" hour="4" monthday="9" month="10"/>
        <onset minute="0" hour="4" monthday="9" month="10"/>

        <onset name="Christmas Day"
               minute="0" hour="4" monthday="24" month="11"/>
        <onset minute="0" hour="4" monthday="24" month="11"/>
    </interval>
</schedule>

2023 US Federal Holidays.xml

C++ fragment
using fixed_duration_as = timepiece_settings::fixed_duration_as;

interval_schedule_data sd2{year_interval, L"2023 US Federal Holidays"};
sd2.appdata = fixed_duration_as::inverse_fixed_duration;
sd2.active_from = {date(2023, 1, 1), time_duration(0, 0, 0)};
sd2.active_until = {date(2024, 1, 1), time_duration(0, 0, 0)};
sd2.blueprint = onset_series_blueprint::fixed_subrange_duration;
// 5 onset/completion pairs
sd2.cycle.resize(5 * 2);
sd2.cycle[0] = {0, 0, 4, 1, 0, 0};   // New Year's Day (Observed)
sd2.cycle[1] = {0, 0, 4, 1, 0, 0};   //
sd2.cycle[1] = {0, 0, 4, 18, 5, 0};  // Juneteenth
sd2.cycle[2] = {0, 0, 4, 18, 5, 0};  //
sd2.cycle[3] = {0, 0, 4, 3, 6, 0};   // Independence Day
sd2.cycle[4] = {0, 0, 4, 3, 6, 0};   //
sd2.cycle[5] = {0, 0, 4, 9, 10, 0};  // Veterans Day (Observed)
sd2.cycle[6] = {0, 0, 4, 9, 10, 0};  //
sd1.cycle[7] = {0, 0, 4, 24, 11, 0}; // Christmas Day
sd1.cycle[8] = {0, 0, 4, 24, 11, 0}; //

Inauguration Day

This holiday repeats every 4 years following a U.S. presidential election. Hence it is necessary to fix the schedule's start period at a certain year.

Additionally, the same rule for a federal holiday falling on a weekend applies (on a Saturday it is usually observed on the preceding Friday; on a Sunday it is usually observed on the following Monday). That's why we fix it at a specific year or at the end of a sequence of years where we know the dates are the same.

[Note] Note

The requirement to repeat the holiday "every 4 years" is represented with length="4" in XML, and with interval_schedule_data::factor=4 in C++.

XML fragment
<fds:schedules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fds="http://xml.firedaemon.com/scheduling/v3" xmlns:fd="http://xml.firedaemon.com">
    <schedule name="2021, 2025 Inauguration Day" fd:fixed_duration_as="downtime">
        <activity_boundary from="2021-01-01T00:00:00" until="2029-01-01T00:00:00"/>
        <interval xsi:type="fds:attributive_interval" granularity="year_interval" length="4" blueprint="fixed_subrange_duration">

            <onset name="Inauguration Day"
                   minute="0" hour="4" monthday="19" month="0"/>
            <onset minute="0" hour="4" monthday="19" month="0"/>
        </interval>
    </schedule>
</fds:schedules>

2021, 2025 Inauguration Day.xml

C++ fragment
interval_schedule_data sd3{year_interval, L"2021, 2025 Inauguration Day"};
sd3.appdata = fixed_duration_as::inverse_fixed_duration;
// must fix the schedule at its beginning because it repeats every 4 years
sd3.active_from = {date(2020, 1, 1), time_duration(0, 0, 0)};
// must fix the schedule at its end because Inauguration Day date changes in 2029
sd3.active_until = {date(2029, 1, 1), time_duration(0, 0, 0)};
sd3.interval.factor = 4;
sd3.blueprint = onset_series_blueprint::fixed_subrange_duration;
// 1 onset/completion pair
sd3.cycle.resize(1 * 2);
sd3.cycle[0] = {0, 0, 4, 19, 0, 0}; // Inauguration Day
sd3.cycle[1] = {0, 0, 4, 19, 0, 0}; //

Restart schedule

It may be useful to restart the program running as a service on a daily basis. This schedule restarts the program daily at 4AM.

When you want to restart the program periodically, a single Restart schedule is sufficient - Restarts only occur within uptime (reversely they are ignored during downtime).

XML fragment
<fds:schedules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fds="http://xml.firedaemon.com/scheduling/v3" xmlns:fd="http://xml.firedaemon.com">
    <schedule name="Restart daily at 4AM">
        <interval xsi:type="fds:attributive_interval" granularity="day_interval" length="1" blueprint="evenly_clocked">
            <onset minute="0" hour="4"/>
        </interval>
    </schedule>
</fds:schedules>
C++ fragment
interval_schedule_data sd4{year_interval, L"Restart daily at 4AM"};
sd4.blueprint = onset_series_blueprint::evenly_clocked;
// A single onset
sd4.cycle.resize(1 * 1);
sd4.cycle[0] = {0, 0, 4};

PrevUpHomeNext