Skip to content

Commit eaa2380

Browse files
committed
feat(v2): upgrade module to v2, rewrite engine with interval math, and remove legacy API
1 parent 51e93e3 commit eaa2380

4 files changed

Lines changed: 875 additions & 601 deletions

File tree

README.md

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,57 @@
11
# openhours
22

3-
A compromise of complexity of the ["opening_hours"](https://wiki.openstreetmap.org/wiki/Key:opening_hours).
4-
Only the `day-day time-time" will work for now.
3+
A high-performance Go parser and evaluator for OpenStreetMap [`opening_hours`](https://wiki.openstreetmap.org/wiki/Key:opening_hours) specifications.
54

6-
## Online tools
5+
## Features
6+
7+
- **Interval Math**: Bakes rules into disjoint week-minute time windows without bitset scanning.
8+
- **Fast Evaluation**: $O(\log N)$ point-in-time checks via binary search.
9+
- **Instance Interning**: Caches and shares identical schedules concurrently to minimize memory allocations.
10+
- **Overnight Shifts**: Supports shifts spanning across midnight (e.g. `Mo 22:00-04:00`, `Su 22:00-04:00`).
11+
- **Overrides & Exclusions**: Supports `off` / `closed` rules overriding previous rules (e.g. `Mo-Su 00:00-24:00; Tu 12:00-13:00 off`).
12+
- **Shortcuts & Open-Ended Intervals**: Supports `24/7`, open-ended (`Mo 10:00+`), day-only rules (`Mo-Fr`), and time-only rules (`10:00-12:00`).
13+
- **Duration Queries**: Find when an opening window long enough for a task of duration $D$ is available (`GetTimeToOpenForDuration` / `When`).
14+
- **JSON Support**: Native `json.Marshaler` and `json.Unmarshaler` implementations.
15+
16+
## Online Tools
717

818
<https://openingh.openstreetmap.de/evaluation_tool/?setLng=en>
919

10-
## Example
20+
## Examples
1121

12-
```go
13-
oh := openhours.New("Mo-Fr 09:00-17:00")
14-
t := time.Date(2019, 3, 6, 10, 0, 0, 0, time.Now().Location())
15-
// oh.Location = t.Location() //default to system but can be changed this way
22+
### Modern API (`OpeningHours`)
1623

17-
fmt.Println("t =", t)
24+
```go
25+
package main
1826

19-
isOpen := oh.Match(t)
20-
fmt.Println("Is it open at this date?", isOpen)
27+
import (
28+
"fmt"
29+
"time"
2130

22-
_, duration := oh.NextDur(t)
23-
fmt.Println("For how long?", duration)
31+
"github.com/chneau/openhours/v2"
32+
)
2433

25-
_, date := oh.NextDate(t)
26-
fmt.Println("When will it close?", date)
34+
func main() {
35+
// Parse an OSM opening_hours expression
36+
oh := openhours.Parse("Mo-Fr 08:00-12:00, 13:00-17:00; Sa 08:00-12:00")
2737

28-
fmt.Println(" +++++++++++++++++++++ ")
38+
now := time.Date(2026, 5, 18, 10, 0, 0, 0, time.UTC) // Monday 10:00 AM
2939

30-
t = time.Date(2019, 3, 6, 18, 0, 0, 0, time.Now().Location())
40+
// Check if open
41+
fmt.Println("Is open:", oh.IsOpen(now)) // true
3142

32-
fmt.Println("t =", t)
43+
// Get current shift end
44+
if end := oh.GetCurrentShiftEnd(now); end != nil {
45+
fmt.Println("Current shift ends at:", *end) // 2026-05-18 12:00:00
46+
}
3347

34-
isOpen, date = oh.NextDate(t)
35-
fmt.Println("Is it open?", isOpen, "Ok, when will it open then ?", date)
48+
// Time to next open
49+
wait := oh.GetTimeToOpen(time.Date(2026, 5, 18, 12, 30, 0, 0, time.UTC))
50+
fmt.Println("Opens in:", *wait) // 30m
3651

37-
/* output
38-
t = 2019-03-06 10:00:00 +0000 GMT
39-
Is it open at this date? true
40-
For how long? 7h0m0s
41-
When will it close? 2019-03-06 17:00:00 +0000 GMT
42-
+++++++++++++++++++++
43-
t = 2019-03-06 18:00:00 +0000 GMT
44-
Is it open? false Ok, when will it open then ? 2019-03-07 09:00:00 +0000 GMT
45-
*/
52+
// Find wait time for continuous duration (e.g. 3-hour job)
53+
waitDur := oh.GetTimeToOpenForDuration(time.Date(2026, 5, 18, 11, 0, 0, 0, time.UTC), 3*time.Hour)
54+
fmt.Println("Wait for 3h slot:", *waitDur) // 2h (opens at 13:00)
55+
}
4656
```
57+

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
module github.com/chneau/openhours
1+
module github.com/chneau/openhours/v2
22

3-
go 1.20
3+
go 1.22

0 commit comments

Comments
 (0)