Opening Hours to JSON - Normalize Google Maps Business Hours
Pricing
$0.50 / 1,000 place normalizeds
Opening Hours to JSON - Normalize Google Maps Business Hours
Google Maps and Yelp give you hours as messy text. Pick the scraper's dataset and get weekly JSON, schema.org openingHoursSpecification and an open-now flag per place, with 24/7, closed and split-shift handling and day names in many languages. No re-scraping.
Pricing
$0.50 / 1,000 place normalizeds
Rating
0.0
(0)
Developer
mohamed alaya
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
16 days ago
Last modified
Categories
Share
Turns the messy opening-hours text from Google Maps, Yelp and other place scrapers into clean weekly JSON, schema.org openingHoursSpecification and an "open now" flag.
Built for people who already scraped thousands of places and now have to make sense of "Mon-Fri 9 AM to 5 PM, Sat 10-2" in ten different formats.
Quick start: use it after a Google Maps scraper
- Run your Google Maps scraper (Compass, Lukas Krivka or any other).
- Start this Actor, pick that run's dataset in Google Maps / places dataset(s).
- Download the output as JSON, CSV or Excel.
Run it with empty input to see a demo of 8 places in English, French, German and Spanish.
Input examples
1. Dataset from a Google Maps scraper
{ "datasets": ["<pick with the dataset picker>"] }
2. Pasted rows, with coordinates for the time zone
{"rows": [{ "title": "Joe's Pizza", "openingHours": "Mon-Fri 9:00-17:00; Sat 10:00-14:00; Sun closed", "location": { "lat": 40.73, "lng": -74.0 } }]}
3. Plain hours strings, one fixed time zone, test a specific moment
{"rows": ["lundi au vendredi 9h-18h, samedi 10h-13h", "Open 24 hours"],"defaultTimezone": "Europe/Paris","checkAt": "2026-12-24T18:30:00+01:00"}
Input guide
| Field | What it does |
|---|---|
datasets | Pick one or more datasets (the picker gives the Actor read permission). |
rows / rowsCsv | Paste JSON rows, a JSON array or a CSV with a header row. |
hoursField | Name of the column holding the hours. Empty = auto-detect openingHours, opening_hours, hours, businessHours, workingHours and similar. |
defaultTimezone | IANA zone (e.g. Europe/Paris) used when a row has no coordinates or time zone. |
checkAt | ISO date-time to test open/closed at, in each place's own time zone. Empty = now. |
keepAllFields | Copy every original column to the output (default on). |
maxRows | Safety limit per run. |
What it understands
- Google Maps
openingHoursarrays ({day, hours}), plain text blocks, compact text such asMo-Fr 09:00-17:00; Sa 10:00-14:00(OSM-style short day names), Yelpopenarrays (start/end/day), and objects keyed by day name. - 12-hour and 24-hour times,
9-5,9h30,09.00,9:00 Uhr, narrow no-break spaces and en-dashes from Google. - Split shifts, overnight hours (
10 AM to 4 AM),Open 24 hours,24/7,Closed, "permanently/temporarily closed". - Day names in English, French, German, Spanish, Italian, Portuguese, Dutch, Swedish, Danish/Norwegian, Polish, Turkish, Indonesian, Russian, Arabic, Chinese and Japanese, plus "weekdays", "weekends", "daily".
Output
One row per input row. Your original fields are kept and these are added:
| Field | Meaning |
|---|---|
hoursStatus | parsed, partial (some lines not understood), unparsed or no-hours-field. |
openingHoursText | Compact text, e.g. Mo-Fr 09:00-17:00; Sa 10:00-14:00; Su off. |
hoursWeekly | {monday:[{open:"09:00",close:"17:00"}], ...}. An empty list means closed. close:"24:00" = midnight, overnight:true = ends the next day. |
hours_mon ... hours_sun | One flat text column per day, handy for CSV/Excel. |
openingHoursSpecification | schema.org array, ready for JSON-LD. |
is24x7, weeklyOpenHours | 24/7 flag and total open hours per week. |
timezone, timezoneSource | IANA zone from a field, from coordinates, or your fallback. |
isOpenNow, openStatus | Open now at checkAt (or now), e.g. Open until 17:00 or Closed, opens Tue 09:00. null if the time zone is unknown. |
assumedClosedDays | Days that were not mentioned in the text and are treated as closed. |
unparsedLines | Lines the parser could not read, so you can review them. |
Sample row (shortened):
{ "title": "Boulangerie Paul", "hoursStatus": "parsed", "openingHoursText": "Mo-Fr 07:00-20:00; Sa 08:00-19:00; Su off", "timezone": "Europe/Paris", "timezoneSource": "coordinates", "isOpenNow": false, "openStatus": "Closed, opens Mon 07:00", "weeklyOpenHours": 91 }
Use it with
Google Maps scraper -> this Actor -> your CRM, delivery app or local-SEO tool. It pairs naturally with the Google Maps Emails Actor from the same author: enrich the contacts, normalize the hours.
FAQ
Does it call any website or API? No. Parsing and time zone lookup are offline; the only read is your own dataset.
Why is isOpenNow null? The row had no coordinates or time zone field and you set no fallback time zone.
Is it OSM opening_hours syntax? It reads the common short form (Mo-Fr 09:00-17:00) but not the full OSM grammar (public holidays, week numbers, months).
Honest limits
- Text it cannot read ("Call for hours", seasonal rules, holiday exceptions) is reported in
unparsedLines, never guessed. Holiday and special-day hours are not modelled. - Bare
9-5is read as 09:00-17:00; ambiguous short forms in other languages may be wrong, checkhoursStatusand the sample before bulk use. - Time zones come from coordinates (offline lookup near borders can be off).
Price
Pay per event: $0.0005 per place normalized (only rows where hours were found and delivered; unreadable or hour-less rows are free). 1,000 places = $0.50, 50,000 places = $25.