Skip to content

yauhen-l/openhours

Repository files navigation

openhours Build Status

golang implementation of opening hours (inspired by OpenStreetMap opening hours: http://wiki.openstreetmap.org/wiki/Key:opening_hours)

This Go library let you define time intervals in human-readable form and then check if specified time matches this interval.

Install

Run go get github.com/yauhen-l/openhours

Usage

package main

import (
    "fmt"
    "time"

    "github.com/yauhen-l/openhours"
)

func main() {
	oh, errs := openhours.CompileOpenHours("Mo-We 06:00-17:00")
	if len(errs) > 0 {
	  fmt.Printf("%v\n", errs)
	  return
	}

	// Simple check if currently open
	fmt.Println("Currently open:", oh.Match(time.Now()))

	// Get detailed status information
	isOpen, nextChange, duration := oh.MatchExt(time.Now())
	if isOpen {
		fmt.Printf("Open! Will close at %v (in %v)\n",
			nextChange.Format("15:04"), duration)
	} else {
		if nextChange.IsZero() {
			fmt.Println("Closed (never opens)")
		} else {
			fmt.Printf("Closed. Will open at %v (in %v)\n",
				nextChange.Format("Mon 15:04"), duration)
		}
	}
}

API Reference

Match(time.Time) bool

Returns true if the location is open at the given time, false otherwise.

MatchExt(time.Time) (isOpen bool, nextChange time.Time, duration time.Duration)

Returns detailed status information:

  • isOpen: whether currently open
  • nextChange: when status will next change (zero time if never changes, e.g., for "24/7")
  • duration: how long until the status change
// Business hours example
oh, _ := openhours.CompileOpenHours("Mo-Fr 09:00-17:00")

// Tuesday 2 PM
isOpen, nextChange, duration := oh.MatchExt(time.Date(2023, 6, 13, 14, 0, 0, 0, time.UTC))
// isOpen: true
// nextChange: Tuesday 17:00
// duration: 3h0m0s

// Tuesday 8 PM
isOpen, nextChange, duration = oh.MatchExt(time.Date(2023, 6, 13, 20, 0, 0, 0, time.UTC))
// isOpen: false
// nextChange: Wednesday 09:00
// duration: 13h0m0s

Examples

OpenHours simplified pattern:

OpenHours = (days(,days)*)? (MMM)? (Wds(,Wds)*)? (timespan(,timespans)*)?

days = day | day-day       #Days of month
Wds = Wd | Wd-Wd           #Weekdays
timespan = hh:mm-hh:mm     #Day time range
Openhours Description
24/7 Matches everything
24 Dec Any time on 24th of December
01-05 Any time from 1st till 5th of any month
18:00-18:30 Any day from 6PM till 6:30PM
Sa,Su 10:00-22:00 From 10AM till 10PM on Saturday and Sunday
Mo; Tu 9:00-15:00 Any time on Monday and from 9AM till 3PM on Tuesday

OpenStreetMap Specification Compatibility

This table shows which features from the OpenStreetMap opening_hours specification are currently supported:

Feature Status Examples Notes
Time Formats
Basic 24-hour (HH:MM) 08:00-17:00 Fully supported
Multiple time intervals 08:00-12:00,13:00-17:00 Comma-separated
Time validation Hours 0-24, minutes 0-59 Full validation
24:00+ format 18:00-26:00 Not supported
Open-ended times 18:00+ Not supported
Variable times sunrise-sunset Not supported
Weekdays
Individual weekdays Mo, Tu, We, Th, Fr, Sa, Su All supported
Weekday ranges Mo-Fr, Sa-Su Fully supported
Multiple weekdays Mo,We,Fr Comma-separated
Nth occurrence Su[1] (first Sunday) Not supported
Dates and Months
Day of month 20 (20th of any month) Fully supported
Day ranges 01-05, 20-25 Fully supported
Month names Jan, Feb, Mar, etc. All abbreviations
Day with month 20 Mar, 24 Dec Fully supported
Specific years 2024 Jan 10 Not supported
Week numbers week 25 Not supported
Special Values
Always open 24/7 Fully supported
Public holidays PH, PH off Not supported
School holidays SH Not supported
Closed/off status off, closed Not supported
Complex Rules
Semicolon separator Mo 10:00-12:00; Tu 14:00-16:00 Overwriting rules
Combined patterns 20,21 Mar Mo Day+month+weekday
Comments "children only" Not supported
Colon separator Dec 25: 08:30-20:00 Not supported
Fallback rules Mo-Fr 08:00-18:00 || "by appointment" Not supported

Coverage Summary:

  • Basic features: ~70% - Covers most common use cases
  • Advanced features: ~20% - Missing complex rules and special cases

This implementation focuses on the most commonly used opening hours patterns and provides a solid foundation for typical business hour specifications.

Contribution

If want to extend syntax then you need to install few more packages:

// Lexer
go install github.com/blynn/nex
// Parser
go install github.com/cznic/goyacc

And make sure that both nex and goyacc are in the path

To verify changes:

go generate && go test -v

About

golang implementation of opening hours

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors