Giter Club home page Giter Club logo

parse-opening-hours's Introduction

Python Opening Hours parser

CircleCI codecov Downloads

This library parses opening hours from various human-readable strings such as "Mon- Fri 9:00am - 5:30pm" into a more standard JSON format that can be processed more easily.

The format

opening_hours = [
	{
		"day": "monday",
		"opens": "9:00",
		"closes": "17:00"
	},
	//..
]

Installation

pip install parse-opening-hours

Usage

The simplest example is just printing the JSON for an opening hours string:

from opening_hours import OpeningHours

print(OpeningHours.parse("Mon- Fri 9:00am - 5:30pm").json())

This should give you the below output:

[
	{'day': 'monday', 'opens': '9:00', 'closes': '17:30'},
	{'day': 'tuesday', 'opens': '9:00', 'closes': '17:30'},
	{'day': 'wednesday', 'opens': '9:00', 'closes': '17:30'},
	{'day': 'thursday', 'opens': '9:00', 'closes': '17:30'},
	{'day': 'friday', 'opens': '9:00', 'closes': '17:30'}
]

This has been tested using Python 3.8.5

Documentation

In addition to this README, there is some documentation generated from inline documentation comments. This is available at https://moralcode.github.io/parse-opening-hours/

Environment variables

Setting the environment variable OH_DEBUG to a value of Y will set the root logging level to debug and will cause log entries to appear in stdout for debugging purposes

Troubleshooting

Assumptions

When specifying a time without AM or PM indicators, you may get an error that reads TypeError: Cannot convert a time of unknown type (AM, PM or 24H) without assuming its type.. To resolve this, pass assume_type=TimeType.AM when calling the parse() function. This will use AM in place of an unknown AM or PM designation. In cases like the string "9-5", if the second value in the range (in this case the 5 is smaller than the first (i.e. the 9) then it will be converted to PM automatically

Tests and Coverage

run pytet and generate coverage database pipenv run pytest --cov=./

show coverage report: pipenv run coverage report

parse-opening-hours's People

Contributors

moralcode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

parse-opening-hours's Issues

Automatically combine adjacent times

For example, something that would otherwise parse to:

[{"day": "sunday", "opens": "09:00", "closes": "17:00"}, {"day": "sunday", "opens": "17:00", "closes": "19:00"}]

would automatically get merged into:

[{"day": "sunday", "opens": "09:00", "closes": "19:00"}]

Breaking API updates

This is an issue for compiling a list of breaking API changes that would be nice to have, but arent really worth doing on their own. The plan is to save them all up and apply them all at once whenever version 1.0 is considered ready.

The list:

  • rename the model classes to have more descriptive names
  • give all the model classes a consistent API (and maybe create some superclass or interface for this?)
    • make the parse() methods on each class generic (using fields and methods defined by the model classes) and pull it up into a superclass for deduplication
  • convert the constructor of the Days class to a class method from_range and make a simpler constructor (this will require some pretty major refactoring)
  • #3
  • rename Times to TimeRange and create a class Times that can store multiple TimeRange's similar to Days (see #5)
  • make is_24_hr() and is_12_hour() in Time consistent
  • create a common system for specifying assumptions to make when the information is not available (for AM/PM, and century/year)
  • make all the from_parse_results methods consistent with regard to if they are processing a clean dictionary or a pyparsing.ParseResult object and possibly rename them to from_parse_result_dict

make sure "special" apostrophes are also handled

a string like Tuesday’s has a single left-facing apostophe () in it, which is not the same as a "regular" straight apostrophe (').

Need to double check whether this is currently handled by the unicode normalizing or the pyparsing patterns and if not, handle it. Also, regardless, there should be a unit test to make sure that this doesnt become an issue later

apparrently there is a schema.org spec for this kind of thing

"openingHoursSpecification":[{"@type":"OpeningHoursSpecification","opens":"10:00:00","closes":"19:00:00","dayOfWeek":"https://schema.org/Monday"},{"@type":"OpeningHoursSpecification","opens":"10:00:00","closes":"19:00:00","dayOfWeek":"https://schema.org/Tuesday"},{"@type":"OpeningHoursSpecification","opens":"10:00:00","closes":"19:00:00","dayOfWeek":"https://schema.org/Wednesday"},{"@type":"OpeningHoursSpecification","opens":"10:00:00","closes":"19:00:00","dayOfWeek":"https://schema.org/Thursday"},{"@type":"OpeningHoursSpecification","opens":"10:00:00","closes":"19:00:00","dayOfWeek":"https://schema.org/Friday"},{"@type":"OpeningHoursSpecification","opens":"12:00:00","closes":"17:00:00","dayOfWeek":"https://schema.org/Saturday"}],

make known sub-components available for parsing

if a data source is already partially formatted,like this:

"hours": {
	"friday": "700AM-400PM",
	"monday": "700AM-400PM",
	"sunday": "Closed",
	"tuesday": "700AM-400PM",
	"saturday": "730AM-400PM",
	"thursday": "700AM-400PM",
	"wednesday": "700AM-600PM"
},

then it would be nice to be able to just parse the time range.

this should be straighforward as tweaking the internal API so its consistent with the public one and making a new release.

just leaving it here as a TODO

  • Times
  • Time (?)
  • Days
  • Day

Consider renaming package

Despite having jsonify in the name, this is mainly a general parser for opening hours strings that can be made to output to pretty much any format.

Might be nice to swap to a new name early on

Detect and separate notes

Sometimes notes are included in opening hours strings:

By appointment
By appointment. Schedule in MyChartPLUS or by phone.
F: Hours Vary; By appointment; Clinics are usually held on Friday mornings. Time and location is usually to-be-determined the week of the clinic and subject to change. Individuals will be givien the location and time when scheduling appointment.
M,T,W: 9am-4pm; By appointment

Would probably be useful to find a solid way to detect these and make them available separately from the times themselves. Some problems this might pose:

  • notes arent as universally structured as date or time ranges are
  • associating notes with one specific day might require significant work given how multi-day handling is implemented

support parsing individual opening dates

the schema from vaccine-feed-ingest supports this:

opening_dates: [
    {
      opens: str as date that facility opens in iso8601 format e.g. 2021-04-15,
      closes: str  as date that facility closes in iso8601 format e.g. 2021-06-15,
    },
    ...
  ],
  opening_hours: [
    {
      day: str as lowercase day of week e.g. monday,
      opens: str as time with facility opens on this day in format hh:mm,
      closes: str as time with facility closes on this day in format hh:mm,
    },```

handle full iso datetime format

2021-07-11T11:54:00.000+00:00

should be pretty easy since i think pyparsing supports this pattern already. Still need to figure out how to get it to work with the Classes for handling a specific date

Handle small typos and other small mistakes

It would be nice to be able to pass in real-world opening hours data that may have some typos and have this library automatically handle that.

Maybe a more complex solution would be better but for now an easy solution to this would be to change some of the patterns that currently use CaselessMatch for parsing so they can tolerate a certain number of incorrect characters and still be considered valid.

This "ignore up to x typos" functionality does not currently exist in this specific class in pyparsing, although it exists in other classes (CloseMatch if i recall correctly). There is currently an open PR in pyparsing to add this functionality.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.