Chronos

Dates, times, events, schedules and calendars: the easy way

Dealing with calendar dates just isn’t all that fun: there are so many different scales and bases (60 seconds in a minute, 24 hours in a day, etc) and arbitrary rules (31 days in January, but 28 in February… most of the time) that it can be quite a pain.  Oftentimes there’s just no getting around it, but Chronos can sooth the hurt!

Chronos is a C++ library that makes manipulating date-times easy in order to perform scheduling, setup calendars and find points in time that are of interest.  It is designed to work on the smallest embedded systems, like low-memory Arduino, and it should be usable on pretty much anything.

Typical things you’d ask of Chronos might include stuff like:

  • Give me a DateTime for the following Tuesday;
  • How many days until my birthday?
  • Setup a recurring event, 2 hours long, every day (or week, or month or year)
  • When is my next monthly Council of Elders meeting?
  • List the 10 previous occurrences of event XYZ, etc.

It is comprised of three major components:

  1. DateTimes and Spans: object-oriented date-time objects that can be manipulated in many ways
  2. Time marks: sets of timeline points like “every Sunday at 15h00” or “every first of the month”
  3. Calendar Events and Occurrences: actual events with fixed or repeating datetimes of specific duration, and the scheduling functions needed to find events occurrences.

There extensive documentation available, but as a quick introduction to the Chronos style and features, here’s a sample snippet of code:

    // create a datetime, 2 hours from "now"
    Chronos::DateTime inAWhile = Chronos::DateTime::now() + Chronos::Span::Hours(2);

    // mm, lets make that a bit later actually
    inAWhile += Chronos::Span::Minutes(20) + Chronos::Span::Seconds(10);

    // how long until the following tuesday?
    int numDaysTilTuesday = (inAWhile.next(Chronos::Weekday::Tuesday) - inAWhile).days()

    // add an event to a calendar, my yoga class every monday morning:
    MyCalendar.add(
           Chronos::Event(MY_YOGA_CLASS_EVENT_ID,
                 Chronos::Mark::Weekly(Chronos::Weekday::Monday, 8, 30),
                 Chronos::Span::Hours(1)));

    // find the next 5 classes, from now
    Chronos::Event::Occurrences myClasses[5];

    MyCalendar.listNext(5, myClasses, Chronos::DateTime::now());
    for (int i=0; i<5; i++)
    {
	// use myClasses[i].start and myClasses[i].finish DateTimes however you like
    }
    // etc.

What Chronos doesn't do is keep the time.  The clock source is something else, an RTC or whatever you want to configure, normally using the Arduino Time library.

Requirements

Time keeping

Chronos is about manipulating date-times and calendars but, to figure out the actual current time it uses an external component: currently the Arduino Time library is supported, but it should be adaptable to any clock source offering similar functionality.

Platform

You'll also need some hardware to run it on. Basically anything that supports the Arduino SDK should work as-is (including true-blue Arduino and any compatibles, like the BLE Nano or various ESP8266 systems).

As mentioned, the code currently relies on the Time library but moving to another clock source and hence a whole lotta other hardware, should be pretty easy. Get in touch if you need help in this regard, or want to contribute modifications to the library to support new stuff.

Design

Chronos is cross-platform but specifically designed for use on embedded systems, like Arduino.  It uses a 24 hour clock and 4 digit years.

Its priorities are:

  1. Offering intuitive interaction with date-times and calendar events;
  2. Minimizing memory usage; and, finally
  3. Performance.

In order to run of very small devices RAM usage trumps optimization, whenever there's a trade-off to be made.  Still, an old laptop can setup a calendar 65,000 times and locate over 2,000,000 event occurrences in under 15 seconds. Performance numbers are much lower on an ATMega328, of course, but still very usable.

Most importantly, the library eats up very little memory.  For instance, you can manage a calendar with 10 recurring events in only 415 bytes!

Limitations

Chronos has a few limitations and caveats.  These are mainly:

  • it uses an external library (Time) to do timekeeping and determine the current time and date;
  • through it's timekeeper, it bases everything on the Unix epoch;
  • the granularity is seconds -- nothing smaller is handled;
  • the epoch starts in 1970 -- no dates before that handled;
  • the epoch (in seconds) is currently held in a 32-bit variable, so upper-most date is somewhere in 2106 (see DateTime::endOfTime()); and
  • as mentioned, the main concern is embedded system memory, so when a trade-off needs to be made between CPU cycles and RAM, RAM usually wins at the cost of more computing.

License

Chronos is open source software, released under the LGPL.

More

Find out how to use the library in your own programs and the follow the installation directives to get started.