Repository: alltheplaces/alltheplaces

Issue:
Loblaws & Superstore & Thirfty Foods & Fairway's Market & Safeway & Save on Foods & Farmboy
- [x] [Loblaws](https://www.loblaws.ca/store-locator)
- [x] [Superstore](https://www.realcanadiansuperstore.ca/store-locator)
- [x] [Thrifty Foods](https://www.thriftyfoods.com/find-a-store)
- [x] [Fairways](http://www.fairwaymarkets.com/index.php/store-locations)
- [x] [Safeway](https://www.safeway.ca/find-a-store) #311
- [x] [Save on Foods](https://shop.saveonfoods.com/chain/8E4E398?hash=locator&_ga=1.168908327.789228674.1484454975)
- [x] [Farm Boy](https://www.farmboy.ca/about-us/stores/)




Discussion:
I can work on this.
Going to clear the assignee on this so others can work on it. If you're still working on it, please re-assign to yourself and push up what you've got so far.
These should all be broken out into their own tickets. A lot of them have already been done.
working on this.
@iandees , I think this issue should be opened for other stores.
Thanks.

Resolving patch:
diff --git a/locations/spiders/thirty_foods.py b/locations/spiders/thirty_foods.py
new file mode 100644
--- /dev/null
+++ b/locations/spiders/thirty_foods.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+import scrapy
+import json
+import re
+
+from locations.items import GeojsonPointItem
+
+
+class ThirtyFoodsSpider(scrapy.Spider):
+    name = "thirty_foods"
+    allowed_domains = ["www.thriftyfoods.com"]
+    start_urls = (
+        'https://www.thriftyfoods.com/api/en/Store/get?Latitude=48.45423&Longitude=-123.359205&Skip=0&Max=60000',
+    )
+
+    def store_hours(self, store_hours):
+        store_hours = store_hours.replace('Monday', 'Mo').replace('Tuesday', 'Tu').replace('Wednesday', 'We').replace('Thursday', 'Th').replace('Friday', 'Fr').replace('Saturday', 'Sa').replace('Sunday', 'Su')
+        if 'Open 24 hours' in store_hours:
+            return store_hours.replace('Open 24 hours', '00:00-24:00')
+        else:
+            hours = ''
+            match = re.search(r'(\d{1,2}):(\d{2}) (A|P)M - (\d{1,2}):(\d{2}) (A|P)M', store_hours)
+            if match:
+                (f_hr, f_min, f_ampm, t_hr, t_min, t_ampm) = match.groups()
+                f_hr = int(f_hr)
+                if f_ampm == 'P':
+                    f_hr += 12
+                elif f_ampm == 'A' and f_hr == 12:
+                    f_hr = 0
+                t_hr = int(t_hr)
+                if t_ampm == 'P':
+                    t_hr += 12
+                elif t_ampm == 'A' and t_hr == 12:
+                    t_hr = 0
+                
+                hours = '{:02d}:{}-{:02d}:{}'.format(
+                    f_hr,
+                    f_min,
+                    t_hr,
+                    t_min,
+                )
+            return store_hours[:2] + ' ' + hours
+
+    def parse(self, response):
+        results = json.loads(response.body_as_unicode())
+        for store in results['Data']:
+            properties = {
+                'ref': store['Number'],
+                'name': store['Name'],
+                'lat': store['Coordinates']['Latitude'],
+                'lon': store['Coordinates']['Longitude'],
+                'addr_full': store['AddressMain']['Line'],
+                'city': store['AddressMain']['City'],
+                'state': store['AddressMain']['Province'],
+                'postcode': store['AddressMain']['PostalCode'],
+                'phone': store['PhoneNumberHome']['Number'],
+                'opening_hours': self.store_hours(store['OpeningHours'])
+                }
+
+            yield GeojsonPointItem(**properties)
\ No newline at end of file


Test patch: