Synkronize 3.0

Klaus Triendl

Copyright © 2026 FireDaemon

This source code can be used, distributed or modified only under terms and conditions of the accompanying license agreement.

Synopsis

Welcome to FireDaemon’s synkronize library, a C++ library which generates timepoints according to simple yet powerful blueprint patterns. In turn those timepoints may then be consumed to schedule recurring tasks.

Motivating examples include scheduling version checks or tasks on public holidays.

Contents

Introduction

Recurring actions

Tasks are often planned and performed repeatedly, very often recurring in regular intervals. This includes annual events on calendar dates.

Hence what we need is an iterator that is able to iterate over time and date. The Boost Date/Time library is a very powerful library for this. In fact, synkronize utilises the Boost Date/Time library.

The problem is that time/date iterators relate to scheduling like C++ iterators to their respective container/range.

A programmer usually cares less about the iteration process and the necessary iterator — rather the wish is to express when and how often to schedule an action. Ultimately, one needs the timepoints yielded by the iteration process.

It’s all about simplicity and semantically meaningful usage.

Simplicity

Obviously things are getting quickly more complicated if you wanted to deal with multiple calendar dates and certain actions to be triggered — consider e.g. a U.S. Federal Holiday schedule that should suspend a program during these known days of observance.

This is where the huge benefit of synkronize providing a timepoint generator comes into play. It’s a timepiece device that you simply configure how you want it to generate timepoints, and off you go getting sequential timepoints. That’s also the reason why the library focuses on the concept of ‘scheduling’ rather than timepoint iteration.

The synkronize library offers a rich set of features for date/time scheduling.

Yet, there are basically only 4 things to do:

// 1) prepare schedule definition
fd::interval_schedule_data sd{ fd::day_interval };

// 2) create and initialize timepoint generator from schedule definition
fd::schedule_timepiece scheduler{ sd };

// 3) extract generated timepoint as unix timestamp
std::chrono::seconds next = currently_scheduled_at__s(scheduler);

// 4a) advance to next timepoint and extract generated timepoint
next = advance__s(scheduler, fd::timepiece_move::to_adjacent)

// 4b) work with the generated timepoint
next = currently_scheduled_at__s(scheduler);

Features

↑ Back to top

Prerequisites

synkronize was made with independency from operating systems in mind, with only a tiny fraction of platform-dependent code retrieving system or user locale settings.

Using synkronize

Including synkronize headers requires a compiler supporting C++20, from which the following mandatory features are used:

  1. 3-way comparison of onset names
  2. defaulted comparison operators
  3. constant evaluation (std::is_constant_evaluated)

At the time of writing the following compilers are known to work:

3rd-party Dependencies

  1. The Boost Date Time library from Boost 1.77 or later
macOS
  1. CoreFoundation framework

Compilation

msvc
  1. define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING when using boost property tree io functionality (defined in ptree_io.h)

Building synkronize

Building synkronize requires a compiler supporting C++20.

↑ Back to top

Chapter 1. Motivating Examples

Version checking

A simple example of using synkronize’s timepoint generator is performing a version check every now and then according to user preferences.

This example checks every month, week or day for a new version of some fact of your choice.

The actual version check and handling of preferences is irrelevant; the main focus is on the simplicity of using the timepoint generator, whose resulting timepoints are fed into a threadpool timer.

Code Outline

namespace fd {
// fwd decl timepoint generator
class schedule_timepiece;
}


// window of some description
class MyTrayWindow :
    public ATL::CWindowImpl<MyTrayWindow, ATL::CWindow, ATL::CWinTraits<WS_OVERLAPPED>>
{
private:
    // this method gets called initially or on changing settings/preferences
    void SetupVersionCheck();
    void ScheduleNextVersionCheck();

private:
    // version checker of some description
    fd_version_checker vchecker_;

    // the timepoint generator
    std::unique_ptr<fd::schedule_timepiece> vscheduler_;
    // threadpool timer of some description
    threadpool_periodic_timer vtimer_;
};
#include <fd/interval_schedule_data.h>
#include <fd/schedule_timepiece.h>
using namespace fd;

void MyTrayWindow::SetupVersionCheck()
{
    // grab read-only program settings/preferences
    const auto prefs = globalRoSettings->SharedData();

    if (prefs->vcheckInterval == MySettingsStore::VCheckOff)
    {
        vtimer_.cancel();
        vscheduler_ = nullptr;
        return;
    }


    // prepare schedule definition
    interval_schedule_data sd
    {
        prefs->vcheckInterval == MySettingsStore::VCheckMonthly ? month_interval :
        prefs->vcheckInterval == MySettingsStore::VCheckWeekly ? week_interval :
        day_interval
    };
    // create and initialize timepoint generator from schedule definition
    vscheduler_ = std::make_unique<schedule_timepiece>
    (
        sd,
        // first version check should trigger immediately (rewind),
        // changing settings should trigger now or next (adjacent)
        vscheduler_ ? timepiece_move::to_adjacent : timepiece_move::rewind
    );

    // extract generated timepoint as unix timestamp
    std::chrono::seconds next = currently_scheduled_at__s(*vscheduler_);

    // feed timepoint to threadpool timer
    vtimer_.restart(next, winapi_milliseconds::zero(), [this]()
    {
        // might get called any time, retrieve window handle once and check
        if (ATL::CWindow wnd = m_hWnd)
            // message handler method will call MyTrayWindow::ScheduleNextVersionCheck()
            wnd.PostMessage(CheckVersion);
    });
}

void MyTrayWindow::ScheduleNextVersionCheck()
{
    auto checkResult = vchecker_.check_result();
    // not up-to-date -> no need to check anymore
    if (checkResult->checkState == fd_version_check_state::already_checked && !checkResult->isUpToDate)
        return;


    // advance to next timepoint and extract generated timepoint as unix timestamp
    std::chrono::seconds next = advance__s(*vscheduler_, timepiece_move::to_adjacent);

    // feed timepoint to threadpool timer
    vtimer_.restart(next, winapi_milliseconds::zero(), [this]()
    {
        // might get called any time, retrieve window handle once and check
        if (ATL::CWindow wnd = m_hWnd)
            // message handler method will call MyTrayWindow::ScheduleNextVersionCheck()
            wnd.PostMessage(CheckVersion);
    });
}
↑ Back to top

Public Holiday Schedules

One of the finest things you can do with the timepoint generator is to schedule actions for annual events on calendar dates.

Goal For this example we will create a schedule observing the US Federal Holidays, which halts a program during the holiday until the next morning (from 4AM to 4AM), plus a daily restart schedule.

More detailed information about the federal US holidays can be found on https://www.redcort.com/us-federal-bank-holidays/.

synkronize features “Halt” schedules additionally to “Duration” schedules, plus scheduling on a “week day ordinal”, which allows for yet undetermined dates in a month like the “3rd Monday” or a year like the “3rd Monday of January”.

Concepts and properties of a schedule

Let’s take a look at a single ‘Halt Execution’ schedule represented in XML:

<!-- 1. -->
<fds:schedules xmlns:fds="http://xml.firedaemon.com/scheduling/v3"
               xmlns:fd="http://xml.firedaemon.com">

    <!-- 2. -->
    <schedule name="New Year's Day"
              fd:fixed_duration_as="downtime"
              fd:calendar_date_adjustment_rule="us_federal_holiday_observance">

        <!-- 3. -->
        <interval xsi:type="fds:attributive_interval"
                  granularity="year_interval"
                  length="1"
                  blueprint="fixed_subrange_duration">

            <!-- 4. -->
            <onset name="New Year's Day"
                   minute="0" hour="4" monthday="0" month="0"/>
            <onset minute="0" hour="4" monthday="0" month="0"/>
        </interval>

        <!-- 5. -->
        <activity_boundary/>
    </schedule>
</fds:schedules>
  1. There can be one or multiple schedules.
  2. A schedule is defined by time points, denoting either restart, execution duration (uptime) or halt of execution (downtime), and possibly a rule to adjust a date on which the public holiday is actually observed.

    • A schedule has a name, which is optional, but highly recommended, as it is used for display in various places, for identity and makes things much more understandable.
    • The difference between a “Duration” and a “Halt” schedule is defined by the attribute fd:fixed_duration_as="downtime" (→ “Halt”) or fd:fixed_duration_as="uptime" (or its absence) (→ “Duration”).
      Note The fd:fixed_duration_as is a foreign attribute. It’s up to the programmer to handle it.
    • The timepoint generator recognizes rules for adjusting a fixed date when it is actually observed, two of which are built in:
      1. fd:calendar_date_adjustment_rule="us_federal_holiday_observance" — When a legal public 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.
      2. fd:calendar_date_adjustment_rule="us_inauguration_day_observance" — When Inauguration Day falls on a Sunday, it is usually observed on the following Monday.
      Note The fd:calendar_date_adjustment_rule is a foreign attribute. It’s up to the programmer to handle it.
  3. Time points recur in intervals.

    • The scheduling model is designed for different intervals: by the second, by the minute, hourly, daily, weekly, monthly, yearly, by the leapyear. Since the goal is to define a public holiday schedule, consisting of certain days in a year, a ‘yearly’ interval schedule is what we need in this example. The interval’s resolution is called “granularity”, which is set to granularity="year_interval" for a yearly repeating schedule.
    • The blueprint attribute at the interval element tells the timepoint generator how to treat the list of time points (onset elements):
      1. blueprint="evenly_clocked" — lets you freely specify the day of year for each time point in an interval, however the time of all time points will be equalized to the first time point. This rule also applies to the ‘duration’ blueprint values.
      2. blueprint="fixed_duration" — tells it to expect onsets in pairs and consider them as begin and completion of two time points when the application should execute or halt.
      3. blueprint="fixed_subrange_duration" — tells it to expect the onsets in pairs and consider them as begin and completion of a day when the application should execute or halt.
  4. A time point is called onset, in order to express that some action is associated with the time point (similar to music theory).

    An onset’s attributes (second, minute, …) configure when the action should happen, counted from the beginning of the interval (i.e. the beginning of year for a yearly schedule). All offset values are 0-based; i.e. the 5th hour (4 o’clock) is expressed as hour="4", the 11th month (November) is expressed as month="10".

    • To express restarts, only a single onset is needed.
    • To express uptime or downtime, the onsets come in pairs, defining begin and completion (exclusive):
      1. For an uptime (duration) schedule the first onset element marks the start of uptime (the process will be started), the second onset element marks the end of uptime (the process will be terminated).
      2. Conversely, for a downtime (halt) schedule the first onset element marks the start of downtime (the process will be terminated), the second onset element marks the end of downtime (the process will be started).
  5. The activity_boundary fixes a schedule to a certain period. This can be useful for various reasons:

    • In relation to a calendar-based schedule, there may be culturally or politically motivated observance rules. The time generator already recognizes some rules, but there may be rules that are not yet covered. In this case, if you cannot provide custom functions, it may be useful to set the schedule to a specific year.
    • Some holidays may occur every 4 years, which requires a fixed start year.
    • A schedule should simply end.
Note All ‘until time point’ values (i.e. the second onset element of onset/completion pairs) [found at activity boundary, completion time point, end of range] denote an exclusive time point (this makes sense when doing calculations internally, plus it lets you specify periods covering the whole interval easily).

Difference and usefulness of “Halt” and “Duration”

The timepoint generator knows nothing about actions, but only timepoints marking the onset of some action or pairs of timepoints marking onset and completion for an action. In this sense, a “fixed duration” schedule is nothing more than pairs of timepoints marking the begin and completion of whatever you find applicable for your program.

However, differentiating “Halt” from “Duration” is useful when you mix “Duration” (start/stop) and “Halt” (stop/start) schedules and you want to treat both in a uniform way. The timepoint generator has a mode setting that flips stop/start timepoint pairs into start/stop pairs, hence effectively turning the schedule into a regular “Duration” schedule. See fd::timepiece_settings::fixed_duration_as.

Usefulness of “date adjustment rules”

The timepoint generator knows nothing about the culturally or politically motivated observance of public holidays. However, it can be configured to adjust the date as needed. This can be achieved by selecting a function from the set of forwarded date adjustment functions via the corresponding rule name. If the built-in rules are not sufficient, you can create your own C++ adjustment functions.

↑ Back to top

Chapter 2. Glossary

interval (time)
A time interval is the distance or difference between two timepoints on a timescale. If repeated regularly, intervals can be measured in metric units, which are in the context of synkronize: seconds, minutes, hours, days, weeks, months, years.
interval granularity
The ‘granularity’ of a timescale, i.e. another word for “unit”. Units are seconds, minutes, hours, days, weeks, months, years.
interval scale
An interval scale is a metric scale that allows to measure quantity and difference of values in metric units. In regard to time and date, in the context of synkronize, these values are timepoints on a timescale in units like seconds or days.
onset
The term ‘onset’ is borrowed from music theory where it is used to mark the beginning of a note, but doesn’t denote pitch or length. Likewise the onset in regard to timepoint generation for scheduling marks the starting of some action, without specifying the action itself or its duration.
timepoint
A time value on the imaginary timeline.
time bounds
Two timepoints marking beginning and end of a time range, which can be a closed or half-open interval.
↑ Back to top

Reference

Header <fd/algorithm.h>

namespace fd {

  // Check whether given reference time point is not beyond time point bounds;
  // considers possible infinity of boundary.
  template<auto converter = schedule_timepoint_ident,
           time_bounds_notation halfopen = time_bounds_notation::halfopen,
           typename TP>
    bool within_boundary(const TP & tp, const schedule_time_bounds & boundary);
  template<auto converter, typename TP>
    bool within_activity_boundary(const TP &, const schedule_timepiece &);
  template<std::ranges::input_range Rng, typename Proj = std::identity>
    bool all_schedules_completed(const Rng &, Proj && = {});
  template<std::ranges::input_range Rng, typename Proj = std::identity>
    bool any_of_fixed_duration(const Rng &, Proj && = {});
  template<std::ranges::input_range Rng, typename Proj = std::identity>
    bool none_of_fixed_duration(const Rng &, Proj && = {});
  template<std::ranges::input_range Rng, typename Proj = std::identity>
    bool execution_scheduled(const Rng &, scheduling_purpose, Proj && = {});
  template<std::ranges::input_range Rng>
    bool schedule_implicitly_down(const Rng &, scheduling_purpose);
  template<auto converter, typename TP, std::ranges::forward_range Rng>
    std::optional< bool > within_schedule_uptime(const TP &, const Rng &);
  template<std::ranges::forward_range Rng>
    std::optional< schedule_time_bounds >
    uptime_bounds_for(const schedule_timepoint &, const Rng &);
  template<std::ranges::forward_range Rng>
    std::optional< schedule_time_bounds >
    uptime_bounds_for_action_prelude(const schedule_timepiece &, const Rng &);
  template<std::ranges::forward_range Rng>
    std::optional< schedule_time_bounds >
    uptime_bounds_for_action_onset(const schedule_timepiece &, const Rng &);
  bool within_activity_boundary(const schedule_timepoint & now,
                                const schedule_timepiece & schedule);
  template<std::ranges::forward_range Rng>
    std::optional< bool >
    within_schedule_uptime(const schedule_timepoint & now,
                           const Rng & schedules);
  template<std::ranges::forward_range Rng>
    std::optional< bool >
    within_schedule_uptime(time_t now, const Rng & schedules);
  template<std::ranges::forward_range Rng>
    std::optional< bool >
    within_schedule_uptime(std::chrono::system_clock::time_point now,
                           const Rng & schedules);
}

Header <fd/calendar_types.h>

namespace fd {
  namespace gregorian {
    typedef boost::gregorian::date date;
    typedef date::duration_type date_duration;
    typedef date_duration days;
    typedef date::calendar_type calendar;
    typedef boost::date_time::weekdays weekdays;
  }
}

Header <fd/correlating_timepieces_test_player.h>

namespace fd {
  class correlating_timepieces_test_player;
}

Header <fd/date_adjustors.h>

namespace fd {
  struct builtin_calendar_date_adjustor;
  struct builtin_calendar_date_combo_adjustor;

  // Denotes the optional rule for adjusting the result date of an annual
  // schedule of fixed dates.
  enum calendar_date_observance_rule {
    none,
    us_federal_holiday_observance,
    us_inauguration_day_observance
  };

  namespace gregorian {
    struct lockstep_date_days_adjustor;
    struct us_federal_holiday_observance_adjustor;
    struct us_inauguration_day_observance_adjustor;
  }
}

Header <fd/date_iterators.h>

namespace fd {
  namespace gregorian {
    class date_iterator_interface;
    class day_iterator;
    template<typename YearIt> class leapyear_anyday_iterator;
    class leapyear_monthday_iterator;
    class leapyear_weekday_iterator;
    class month_day_iterator;
    class month_weekday_iterator;
    class week_iterator;
    class year_monthday_iterator;
    class year_weekday_iterator;
  }
}

Header <fd/date_time.h>

namespace fd {
  enum iso_weekday_value;
  iso_weekday iso_first_dow_from(special_iso_weekday);
  iso_weekday_value iso_first_dow_from(iso_weekday_value);
  constexpr int convert_weekday(int, int, int);
  constexpr int convert_weekday(int, iso_weekday_value, iso_weekday_value);

  // Calculate offset from a weekday to the following.
  constexpr int
  offset_to_following_weekday(int fromWeekday, int toFollowingWeekday);

  // Calculate negative offset from a weekday to the previous.
  constexpr int offset_to_prev_weekday(int fromWeekday, int toPrevWeekday);
}

Header <fd/date_time_typed.h>

namespace fd {
  struct to_iso_weekday_value;

  // Enumeration of ISO 8601 weekday names.
  enum iso_weekday {
    mon, tue, wed, thu, fri, sat, sun,
    first = mon, second = tue, third = wed, fourth = thu,
    fifth = fri, sixth = sat, seventh = sun,
    last = sun, first_dow = first
  };

  // Enumeration of special designators for locale-based calculations.
  enum special_iso_weekday {
    first_dow_from_system_locale = -1,
    first_dow_from_user_locale = -2
  };

  // Variant holding an iso-based weekday.
  typedef std::variant< iso_weekday, special_iso_weekday > iso_weekday_variant;

  constexpr iso_weekday iso_first_dow_from(iso_weekday);
  constexpr int convert_weekday(int, iso_weekday, iso_weekday);
}

Header <fd/functional.h>

namespace fd {
  enum scheduling_purpose;

  constexpr auto filter_valid_schedules;
  constexpr auto & ts_from_schedule_tp;
  constexpr auto & s_from_schedule_tp;
  constexpr auto & tp_from_schedule_tp;
  constexpr auto & has_schedule_completed;
  constexpr auto & is_schedule_completing;
  constexpr bool operator!(const schedule_timepoint & tp);

  // Check whether given reference time point is not beyond time point bounds.
  template<time_bounds_notation halfopen = time_bounds_notation::halfopen,
           typename TP>
    bool within_timepoint_interval(const TP & tp,
                                   const time_bounds< TP > & interval);

  schedule_timepoint schedule_timepoint_ident(schedule_timepoint tp);
  schedule_timepoint ts_to_schedule_timepoint(time_t ts);
  time_t schedule_timepoint_to_ts(const schedule_timepoint & tp);
  schedule_timepoint s_to_schedule_timepoint(std::chrono::seconds s);
  std::chrono::seconds schedule_timepoint_to_s(const schedule_timepoint & tp);
  schedule_timepoint
  tp_to_schedule_timepoint(std::chrono::system_clock::time_point tp);
  std::chrono::system_clock::time_point
  schedule_timepoint_to_tp(const schedule_timepoint & tp);

  bool has_completed(const schedule_timepiece & schedule);
  bool is_completing(const schedule_timepiece &);
  bool will_complete_after_current_interval(const schedule_timepiece &);
  bool is_action_schedule(const schedule_timepiece & schedule);
  bool is_application_action_schedule(const schedule_timepiece & schedule,
                                      scheduling_purpose purpose);
  bool is_task_execution_schedule(const schedule_timepiece & schedule,
                                  scheduling_purpose purpose);
  bool is_fixed_duration_schedule(const schedule_timepiece & schedule);
  bool is_uptime_schedule(const schedule_timepiece & schedule);
  bool is_downtime_schedule(const schedule_timepiece & schedule);
  bool is_completed_downtime_schedule(const schedule_timepiece & schedule);
  bool is_ongoing_action_schedule(const schedule_timepiece & schedule);
  bool is_completing_application_action_schedule(
    const schedule_timepiece & schedule, scheduling_purpose purpose);
  bool is_completed_application_action_schedule(
    const schedule_timepiece & schedule, scheduling_purpose purpose);
  bool is_completed_task_execution_schedule(
    const schedule_timepiece & schedule, scheduling_purpose purpose);
  bool is_ongoing_fixed_duration_schedule(const schedule_timepiece & schedule);
  bool is_non_operational_interval(const schedule_time_bounds &);
  bool is_non_operational_interval(const schedule_timepiece &);
  bool is_contiguously_up(const schedule_timepiece &);
  bool is_contiguously_down(const schedule_timepiece &);

  // Currently calculated onset time point.
  template<typename R = schedule_timepoint>
    R currently_scheduled_at(const schedule_timepiece & schedule);
  template<auto converter>
    decltype(auto) currently_scheduled_at(const schedule_timepiece & schedule);

  // Currently calculated ending time point.
  template<typename R = schedule_timepoint>
    R currently_ending_at(const schedule_timepiece & schedule);
  template<auto converter>
    decltype(auto) currently_ending_at(const schedule_timepiece & schedule);

  time_t currently_scheduled_at__ts(const schedule_timepiece & schedule);
  time_t currently_ending_at__ts(const schedule_timepiece & schedule);
  std::chrono::seconds
  currently_scheduled_at__s(const schedule_timepiece & schedule);
  std::chrono::seconds
  currently_ending_at__s(const schedule_timepiece & schedule);
  std::chrono::system_clock::time_point
  currently_scheduled_at__tp(const schedule_timepiece & schedule);
  std::chrono::system_clock::time_point
  currently_ending_at__tp(const schedule_timepiece & schedule);

  template<typename R = schedule_timepoint>
    time_bounds< R > convert(const schedule_time_bounds & span);
  template<auto converter>
    auto convert(const schedule_time_bounds & span);

  template<typename R = schedule_timepoint>
    time_bounds< R > current_interval(const schedule_timepiece & schedule);
  template<auto converter>
    decltype(auto) current_interval(const schedule_timepiece & schedule);

  time_bounds< time_t >
  current_interval__ts(const schedule_timepiece & schedule);
  time_bounds< std::chrono::seconds >
  current_interval__s(const schedule_timepiece & schedule);
  time_bounds< std::chrono::system_clock::time_point >
  current_interval__tp(const schedule_timepiece & schedule);

  // Advance timepoint generator.
  template<typename R = schedule_timepoint>
    R advance(schedule_timepiece & schedule, timepiece_move advanceTo,
              const schedule_timepoint & now = schedule_clock::local_time());
  template<auto converter>
    decltype(auto)
    advance(schedule_timepiece & schedule, timepiece_move advanceTo,
            const schedule_timepoint & now = schedule_clock::local_time());
  time_t advance__ts(schedule_timepiece & schedule, timepiece_move advanceTo,
                     const schedule_timepoint & now = schedule_clock::local_time());
  std::chrono::seconds
  advance__s(schedule_timepiece & schedule, timepiece_move advanceTo,
             const schedule_timepoint & now = schedule_clock::local_time());
  std::chrono::system_clock::time_point
  advance__tp(schedule_timepiece & schedule, timepiece_move advanceTo,
              const schedule_timepoint & now = schedule_clock::local_time());

  schedule_timepoint
  derive_clocked_timepoint(const schedule_date & d,
                           const schedule_time_of_day & tod,
                           const interval_onset & onset,
                           interval_granularity g);
  schedule_timepoint
  derive_clocked_timepoint(const schedule_timepoint &, const interval_onset &,
                           interval_granularity);
  timepiece_move
  natural_timepiece_move_setup(const interval_schedule_data &,
                               scheduling_purpose);
  std::tuple< schedule_timepiece &, timepiece_move, schedule_timepoint >
  natural_timepiece_move_arguments(schedule_timepiece &, scheduling_purpose,
                                   const schedule_timepoint & = schedule_clock::local_time());
}

Header <fd/generic_date_adjustor.h>

namespace fd {
  struct generic_date_adjustor;
  struct generic_date_combo_adjustor;
}

Header <fd/generic_date_adjustor_interface.h>

namespace fd {
  // A map of boxed date adjustors named after their rule.
  typedef std::map< std::u8string, shared_date_adjustment_function >
    date_adjustor_map;
  typedef std::shared_ptr< date_adjustor_map > shared_date_adjustor_map;

  // If a US federal holiday falls on a Saturday, it is observed on Friday,
  // if it falls on a Sunday it is observed on Monday.
  constexpr std::u8string_view us_federal_holiday_observance_rule;

  // If US Inauguration Day falls on a Sunday it is observed on Monday.
  constexpr std::u8string_view us_inauguration_day_observance_rule;

  shared_date_adjustor_map make_shared_default_date_adjustor_map();
}

Header <fd/generic_date_adjustor_types.h>

namespace fd {
  // Boxed date adjustor.
  typedef std::function< gregorian::date(gregorian::date) >
    date_adjustment_function;
  // Shared version of a boxed date adjustor.
  typedef std::shared_ptr< date_adjustment_function >
    shared_date_adjustment_function;
}

Header <fd/interval_schedule_definition.h>

namespace fd {
  struct interval_schedule_data;
  class interval_schedule_definition;

  enum onset_series_blueprint_category {
    onset_series_sub_blueprint = INT32_MIN,
    onset_series_duration_blueprint = -(INT32_MIN >> 1)
  };
  enum onset_series_blueprint;

  bool is_category(onset_series_blueprint blueprint,
                   onset_series_blueprint_category category);
}

Header <fd/interval_types.h>

namespace fd {
  struct interval_onset;
  struct interval_onset_duration;
  struct interval_spec;

  enum interval_granularity {
    invalid_interval_granularity = 0,
    second_interval = 0x01, minute_interval = 0x02,
    hour_interval   = 0x04, day_interval    = 0x08,
    week_interval   = 0x10, month_interval  = 0x20,
    year_interval   = 0x40,
    first_interval_granularity = second_interval,
    last_interval_granularity  = year_interval
  };

  enum special_interval_factor {
    numeric_interval_factor  = 0,
    leapyear_interval_factor = -1
  };

  typedef int32_t time_value_t;
  typedef unsigned short greg_value_t;
  typedef std::underlying_type_t< interval_granularity >
    interval_granularity_type;

  constexpr auto time_intervals;
  constexpr auto date_intervals;
  constexpr auto day_intervals;
  constexpr bool synk_any_of_trait_v;
  constexpr bool synk_all_of_trait_v;
  constexpr bool synk_is_any_of_v;
  constexpr bool synk_is_all_of_v;
  constexpr int convert_weekday(const interval_onset &, iso_weekday_value);
  bool operator==(const interval_onset & o2, const interval_onset & o1);
}

Header <fd/multi_timepiece_test_player.h>

namespace fd {
  class multi_timepiece_test_player;
}

Header <fd/ptime_iteration.h>

namespace fd {
  struct ptime_iteration_state;
  bool less_schedule_timepoint(const schedule_timepoint & left,
                               const schedule_timepoint & right);
  bool less_equal_schedule_timepoint(const schedule_timepoint & left,
                                     const schedule_timepoint & right);
}

Header <fd/ptime_iteration_visitors.h>

namespace fd {
  struct progress_ptime_iteration;
  struct regress_ptime_iteration;
  struct yield_next_ptime;
  struct yield_ptime;

  typedef kj::functional_variant_visitor< Visitor >
    functional_ptime_iteration_visitor;
}

Header <fd/ptree_io.h>

namespace fd {
  enum ptree_io_storage { xml, json };

  static std::wstring_convert< std::codecvt_utf8_utf16< wchar_t > > u2u8conv;

  // Read a schedule from a (boost) property tree, encoded in utf-8.
  std::list< interval_schedule_definition >
  read_interval_schedule(
    const boost::property_tree::ptree & rootTree,
    ptree_io_storage storageType,
    const std::function< void(const boost::property_tree::ptree &,
                              interval_schedule_data *) > &
      read_appdata = {});

  void write_interval_schedule(
    boost::property_tree::ptree & rootTree,
    const std::list< interval_schedule_definition > & schedules,
    ptree_io_storage storageType,
    const std::function< void(boost::property_tree::ptree &,
                              const interval_schedule_data &) > &
      write_appdata = {},
    std::initializer_list< std::pair<
      boost::property_tree::ptree::key_type,
      boost::property_tree::ptree::data_type > > ns = {});
}

Header <fd/ptree_io_xml.h>

namespace fd {
  std::list< interval_schedule_definition >
  read_xml_interval_schedule(
    std::istream &,
    const std::function< void(const boost::property_tree::ptree &,
                              interval_schedule_data *) > & = {});

  void write_xml_interval_schedule(
    std::ostream &,
    const std::list< interval_schedule_definition > &,
    const std::function< void(boost::property_tree::ptree &,
                              const interval_schedule_data &) > & = {},
    std::initializer_list< std::pair<
      boost::property_tree::ptree::key_type,
      boost::property_tree::ptree::data_type > > = {});
}

Header <fd/schedule_debugging.h>

namespace fd {
  template<typename Char> struct schedule_timepiece_self_disclosure;

  // Compile human readable status and state information for a timepiece.
  template<typename Char = char>
    schedule_timepiece_self_disclosure< Char >
    self_disclosure(const schedule_timepiece & schedule,
                    scheduling_purpose purpose,
                    schedule_timepoint now = schedule_clock::local_time());

  template schedule_timepiece_self_disclosure< char >
  self_disclosure<char>(const schedule_timepiece &, scheduling_purpose,
                         schedule_timepoint);
  template schedule_timepiece_self_disclosure< wchar_t >
  self_disclosure<wchar_t>(const schedule_timepiece &, scheduling_purpose,
                            schedule_timepoint);
}

Header <fd/schedule_timepiece.h>

namespace fd {
  class schedule_timepiece;
  struct timepiece_setup;

  // Designator describing where to move the timepoint generator's
  // timeline cursor.
  enum timepiece_move {
    rewind,
    to_adjacent_end,
    to_current,
    to_adjacent,
    to_adjacent_begin = to_adjacent,
    to_next
  };
}

Header <fd/scheduling_chrono.h>

namespace fd {
  enum time_bounds_notation;

  typedef boost::posix_time::ptime schedule_timepoint;
  typedef schedule_timepoint::time_duration_type schedule_time_of_day;
  typedef schedule_timepoint::date_type schedule_date;
  typedef schedule_timepoint::date_duration_type schedule_days;
  typedef std::pair< TP, TP > time_bounds;
  typedef time_bounds<> schedule_time_bounds;
  typedef boost::date_time::second_clock< schedule_timepoint >
    schedule_clock;
  typedef schedule_timepoint::time_system_type schedule_time_system;
  typedef schedule_time_system::time_duration_type::traits_type
    schedule_time_traits;
  typedef std::chrono::duration<
    schedule_time_traits::tick_type,
    std::ratio< 1, schedule_time_traits::ticks_per_second > >
      schedule_duration;
}

Header <fd/synkronize_version.h>

SYNKRONIZE_GITDESCRIBE
SYNKRONIZE_GITTAG
SYNKRONIZE_GITABBREVCOMMIT
SYNKRONIZE_GITVERSION
SYNKRONIZE_CURRENTYEAR

Header <fd/timepiece_settings.h>

namespace fd {
  struct timepiece_settings;
}

Header <fd/timepiece_test_player.h>

namespace fd {
  class timepiece_test_player;
}

Header <fd/zeitgeber_types.h>

namespace fd {
  enum zeitgeber_timepoint_type {
    onset,
    ending,
    completion = ending,
    prelude = ending
  };
}
↑ Back to top