opening_hours.js

opening_hours tag is used in OpenStreetMap project to describe time ranges when a specific facility (for example, a cafe) is open. As it has pretty complex syntax which require special parsing and additional processing to extract some useful information (e.g. whether a facility is open at specific time, next time it's going to open/close, or a readable set of working hours), this library was written.

Examples of some complex real-life opening_hours values:

Mo,Tu,Th,Fr 12:00-18:00;Sa 12:00-17:00; Th[3] off; Th[-1] off

a library which works from 12:00 to 18:00 on workdays except Wednesday, and from 12:00 to 17:00 on Saturday. It also has breaks on third and last Thursday of each month.

00:00-24:00; Tu-Su 8:30-9:00 off; Tu-Su 14:00-14:30 off; Mo 08:00-13:00 off

around-the-clock shop with some breaks.

Synopsis

```javascript var oh = new opening_hours('We 12:00-14:00');

var from = new Date("01 Jan 2012"); var to = new Date("01 Feb 2012");

// high-level API { var intervals = oh.getOpenIntervals(from, to); for (var i in intervals) console.log('We are ' + (intervals[i][2] ? 'maybe ' : '') + 'open from ' + (intervals[i][3] ? '("' + intervals[i][3] + '") ' : '') + intervals[i][0] + ' till ' + intervals[i][1] + '.');

var duration_hours = oh.getOpenDuration(from, to).map(function(x) { return x / 1000 / 60 / 60 });
if (duration_hours[0])
    console.log('For a given range, we are open for ' + duration_hours[0] + ' hours');
if (duration_hours[1])
    console.log('For a given range, we are maybe open for ' + duration_hours[1] + ' hours');

}

// helper function function logState(startString, endString, oh, past) { if (past === true) past = 'd'; else past = '';

var output = '';
if (oh.getUnknown()) {
    output += ' maybe open'
        + (oh.getComment() ? ' but that depends on: "' + oh.getComment() + '"' : '');
} else {
    output += ' ' + (oh.getState() ? 'open' : 'close' + past)
        + (oh.getComment() ? ', comment "' + oh.getComment() + '"' : '');
}
console.log(startString + output + endString + '.');

}

// simple API { var state = oh.getState(); // we use current date var unknown = oh.getUnknown(); var comment = oh.getComment(); var nextchange = oh.getNextChange();

logState('We\'re', '', oh, true);

if (typeof nextchange === 'undefined')
    console.log('And we will never ' + (state ? 'close' : 'open'));
else
    console.log('And we will '
        + (oh.getUnknown(nextchange) ? 'maybe ' : '')
        + (state ? 'close' : 'open') + ' on ' + nextchange);

}

// iterator API { var iterator = oh.getIterator(from);

logState('Initially, we\'re', '', iterator, true);

while (iterator.advance(to))
    logState('Then we', ' at ' + iterator.getDate(), iterator);

logState('And till the end we\'re', '', iterator, true);

} ```

Library API

High-level API

Here and below, unless noted otherwise, all arguments are expected to be and all output will be in the form of Date objects.

Simple API

This API is useful for one-shot checks, but for iteration over intervals you should use the more efficient Iterator API.

Iterator API

Features

Almost everything from openinghours definition is supported, as well as some extensions (indicated as EXT: below). For instance, the library is able to process 99.4% of all openinghours tags from Russia OSM data.

Time ranges

Weekday ranges

Month ranges

Monthday ranges

Week ranges

States

Comments

Other

Test

Simple node.js based test framework is bundled. You can run it with node test.js or with make test.

Performance

Simple node.js based benchmark is bundled. You can run it with node benchmark.js or with make benchmark.

On author's Intel Core i5-2400 library allows ~20k/sec constructor calls and ~10k/sec openIntervals() calls with one week period. This may further improve in future.

Author

Contributors

License