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.
These are the 6 holidays, which can be simply repeated every year. This schedule doesn't need to be fixed to a certain year.
<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
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}; //
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.
<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>
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}; //
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 | |
---|---|
The requirement to repeat the holiday "every 4 years" is represented
with |
<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
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}; //
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).
<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>
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};