Evaluation of opening_hours, service_times and collection_times.

Some real world objects change behaviour over time:

  • Shops and facility are opened only at certain times,
  • ferrys run at certain times,
  • there may be night only speed limit for streets,
  • letterboxes are cleared at certain times,
  • busses depart at certain times.

The OpenStreetMap-Database stores such time specifications with keys opening_hours, service_times and collection_times. The Wiki provides an informal description of the allowed values and their meanings.

Based on this description I designed a formal specification and developed a JavaScript implementation.
Without any effort you can evaluate time expressions and become acquainted with their capabilities:

Three maps show the objects from the OSM database using time specifications and mark erroneous ones:

Changes and extensions:

Objects having erroneous opening_hours-values are marked by a red circle on the map. I fixed a big number of them and got quite an overview on what the users store under this key and how. From this I derived some extensions to the proposal:

Cooperative values:

A common mistake was coding additional times in a way that they became interpreted as exclusive times: evaluating the value Mo-Fr 08:00-12:00; We 14:00-18:00 following the proposal, the opening on wednesday ist afternoon only.

I allow additional times separated by , and interprete the comma as and also: Mo-Fr 08:00-12:00, We 14:00-18:00 is evaluated to what the user really wants.

Time is not optional any more:

The proposal defines Mo-Fr as Monday to friday the whole day. But this is wanted very seldomly. Therefore I made the time specification obligatory: Mo-Fr is not allowed any more and must be written as: Mo-Fr 0:00-24:00.


I found quite a lot of time ranges like 22:00-03:00 spanning midnight. The proposals solution is spliting it into two time ranges, one ending at 24:00 on the first day, the other starting at 00:00 on the next day.

This is error prone and in case of complicated date conditions a real mess. Therefore I implemented these Daywraps: if the second time of a time range is lower than the first time, it is assumed to be on the next day.

Date ranges:

Date ranges must be terminated now with a :. This prevents difficult to resolve ambiguities.

Plain text information:

Opening hours can depend on conditions, which cannnot (easily) be evaluated. Lets assume a public pool, which usually is open from 12:00 to 18:00, but closes earlier on bad weather conditions.

To represent such conditions, I add to the status values open and closed a third value unknown, which must be used with a plain text comment.

Addtionally you can use informal only specifications like during the asparagus season.

Error tolerance:

Some errors are quite common: names of weekdays and months are written in other languages or not abbreviated, hours and minutes are separated by . and not by :.

I fix this kind of errors and evaluate the fixed expression, but return the result together with an error message.

The evaluation functions can return open and erroneous at the same time. In the maps this is displayed by circles of two colors.

Open issues:

Holidays (PH und SH)

Public holidays and school holidays depend on the location. I need additional information to select the right rules. I.e. we could use SH(de.nrw) to select school holidays in state North Rhine Westphalia of Germany.

The current implementation evaluates PH to the public holidays of Germany; school holidays are not defined at all.

Sunrise und sunset:

This times can easily be derived from date and location. Unfortunately my lazyness prevented me from porting the equations to JavaScript. If I'm very bored some day, I will make good for this – or if someone asks for it.

Currently I use 06:00 respectively 18:00.


I got started with an halfway comprehensible explanation, but would like somebody else to complete this work. Because I'm too deeply involved into the internals of time value evaluation, I can't take the plain users point of view anymore.