Greasy Fork is available in English.

WME Utils - HoursParser

Parses a text string into hours, for use in Waze Map Editor scripts

Tento skript by nemal byť nainštalovaný priamo. Je to knižnica pre ďalšie skripty, ktorú by mali používať cez meta príkaz // @require https://update.greatest.deepsurf.us/scripts/37486/1395212/WME%20Utils%20-%20HoursParser.js

  1. // ==UserScript==
  2. // @name WME Utils - HoursParser
  3. // @namespace WazeDev
  4. // @version 2024.06.16.000
  5. // @description Parses a text string into hours, for use in Waze Map Editor scripts
  6. // @author MapOMatic (originally developed by bmtg)
  7. // @license GNU GPLv3
  8. // ==/UserScript==
  9.  
  10. // eslint-disable-next-line no-unused-vars
  11. class HoursParser {
  12. constructor() {
  13. this.DAYS_OF_THE_WEEK = {
  14. SS: ['saturdays', 'saturday', 'satur', 'sat', 'sa'],
  15. UU: ['sundays', 'sunday', 'sun', 'su'],
  16. MM: ['mondays', 'monday', 'mondy', 'mon', 'mo'],
  17. TT: ['tuesdays', 'tuesday', 'tues', 'tue', 'tu'],
  18. WW: ['wednesdays', 'wednesday', 'weds', 'wed', 'we'],
  19. RR: ['thursdays', 'thursday', 'thurs', 'thur', 'thu', 'th'],
  20. FF: ['fridays', 'friday', 'fri', 'fr']
  21. };
  22. this.MONTHS_OF_THE_YEAR = {
  23. JAN: ['january', 'jan'],
  24. FEB: ['february', 'febr', 'feb'],
  25. MAR: ['march', 'mar'],
  26. APR: ['april', 'apr'],
  27. MAY: ['may', 'may'],
  28. JUN: ['june', 'jun'],
  29. JUL: ['july', 'jul'],
  30. AUG: ['august', 'aug'],
  31. SEP: ['september', 'sept', 'sep'],
  32. OCT: ['october', 'oct'],
  33. NOV: ['november', 'nov'],
  34. DEC: ['december', 'dec']
  35. };
  36. this.DAY_CODE_VECTOR = ['MM','TT','WW','RR','FF','SS','UU','MM','TT','WW','RR','FF','SS','UU','MM','TT','WW','RR','FF'];
  37. this.THRU_WORDS = ['through', 'thru', 'to', 'until', 'till', 'til', '-', '~'];
  38. // eslint-disable-next-line global-require
  39. this.OpeningHours = require('Waze/Model/Objects/OpeningHour');
  40. }
  41.  
  42. parseHours(inputHours, locale) {
  43. let returnVal = {
  44. hours: [],
  45. parseError: false,
  46. overlappingHours: false,
  47. sameOpenAndCloseTimes: false
  48. };
  49.  
  50. let tfHourTemp, tfDaysTemp, newDayCodeVec = [];
  51. let tempRegex, twix, tsix;
  52. let inputHoursParse = inputHours.toLowerCase().trim();
  53. if (inputHoursParse.length === 0 || inputHoursParse === ',') {
  54. return returnVal;
  55. }
  56. if (/24\s*[\\/*x]\s*7/g.test(inputHoursParse)) {
  57. inputHoursParse = 'mon-sun 00:00-00:00';
  58. } else {
  59. let today = new Date();
  60. let tomorrow = new Date();
  61. tomorrow.setDate(tomorrow.getDate() + 1);
  62. inputHoursParse = inputHoursParse.replace(/\btoday\b/g, today.toLocaleDateString(locale, {weekday:'short'}).toLowerCase())
  63. .replace(/\btomorrow\b/g, tomorrow.toLocaleDateString(locale, {weekday:'short'}).toLowerCase())
  64. .replace(/\u2013|\u2014/g, "-") // long dash replacing
  65. .replace(/[^a-z0-9\:\-\. ~]/g, ' ') // replace unnecessary characters with spaces
  66. .replace(/\:{2,}/g, ':') // remove extra colons
  67. .replace(/closed|not open/g, '99:99-99:99') // parse 'closed'
  68. .replace(/by appointment( only)?/g, '99:99-99:99') // parse 'appointment only'
  69. .replace(/weekdays/g, 'mon-fri').replace(/weekends/g, 'sat-sun') // convert weekdays and weekends to days
  70. .replace(/(12(:00)?\W*)?noon/g, "12:00").replace(/(12(:00)?\W*)?mid(night|nite)/g, "00:00") // replace 'noon', 'midnight'
  71. .replace(/every\s*day|daily|(7|seven) days a week/g, "mon-sun") // replace 'seven days a week'
  72. .replace(/(open\s*)?(24|twenty\W*four)\W*h(ou)?rs?|all day/g, "00:00-00:00") // replace 'open 24 hour or similar'
  73. .replace(/(\D:)([^ ])/g, "$1 $2"); // space after colons after words
  74.  
  75. // replace thru type words with dashes
  76. this.THRU_WORDS.forEach(word => {
  77. inputHoursParse = inputHoursParse.replace( new RegExp(word, 'g'), '-');
  78. });
  79. }
  80.  
  81. inputHoursParse = inputHoursParse.replace(/\-{2,}/g, "-"); // replace any duplicate dashes
  82.  
  83. // kill extra words
  84. let killWords = 'paste|here|business|day of the week|days of the week|operation|times|time|walk-ins|walk ins|welcome|dinner|lunch|brunch|breakfast|regular|weekday|weekend|opening|open|now|from|hours|hour|our|are|and|&'.split("|");
  85. // Remove timezone abbreviations. See https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
  86. killWords.push('acdt','acst','act','act','acwst','adt','aedt','aest','aft','akdt','akst','amst','amt','amt','art','ast','ast','awst','azost','azot','azt','bdt','biot','bit','bot','brst','brt','bst','bst','bst','btt','cat','cct','cdt','cdt','cest','cet','chadt','chast','chot','chost','chst','chut','cist','cit','ckt','clst','clt','cost','cot','cst','cst','cst','ct','cvt','cwst','cxt','davt','ddut','dft','easst','east','eat','ect','ect','edt','eest','eet','egst','egt','eit','est','fet','fjt','fkst','fkt','fnt','galt','gamt','get','gft','gilt','git','gmt','gst','gst','gyt','hdt','haec','hst','hkt','hmt','hovst','hovt','ict','idlw','idt','iot','irdt','irkt','irst','ist','ist','ist','jst','kalt','kgt','kost','krat','kst','lhst','lhst','lint','magt','mart','mawt','mdt','met','mest','mht','mist','mit','mmt','msk','mst','mst','mut','mvt','myt','nct','ndt','nft','npt','nst','nt','nut','nzdt','nzst','omst','orat','pdt','pet','pett','pgt','phot','pht','pkt','pmdt','pmst','pont','pst','pst','pyst','pyt','ret','rott','sakt','samt','sast','sbt','sct','sdt','sgt','slst','sret','srt','sst','sst','syot','taht','tha','tft','tjt','tkt','tlt','tmt','trt','tot','tvt','ulast','ulat','utc','uyst','uyt','uzt','vet','vlat','volt','vost','vut','wakt','wast','wat','west','wet','wit','wst','yakt','yekt');
  87. for (twix=0; twix<killWords.length; twix++) {
  88. tempRegex = new RegExp('\\b'+killWords[twix]+'\\b', "g");
  89. inputHoursParse = inputHoursParse.replace(tempRegex,'');
  90. }
  91.  
  92. // replace day terms with double caps
  93. for (let dayKey in this.DAYS_OF_THE_WEEK) {
  94. if (this.DAYS_OF_THE_WEEK.hasOwnProperty(dayKey)) {
  95. let tempDayList = this.DAYS_OF_THE_WEEK[dayKey];
  96. for (var tdix=0; tdix<tempDayList.length; tdix++) {
  97. tempRegex = new RegExp(tempDayList[tdix]+'(?!a-z)', "g");
  98. inputHoursParse = inputHoursParse.replace(tempRegex,dayKey);
  99. }
  100. }
  101. }
  102.  
  103. // Replace dates
  104. for (let monthKey in this.MONTHS_OF_THE_YEAR) {
  105. if (this.MONTHS_OF_THE_YEAR.hasOwnProperty(monthKey)) {
  106. let tempMonthList = this.MONTHS_OF_THE_YEAR[monthKey];
  107. for (var tmix=0; tmix<tempMonthList.length; tmix++) {
  108. tempRegex = new RegExp(tempMonthList[tmix]+'\\.? ?\\d{1,2}\\,? ?201\\d{1}', "g");
  109. inputHoursParse = inputHoursParse.replace(tempRegex,' ');
  110. tempRegex = new RegExp(tempMonthList[tmix]+'\\.? ?\\d{1,2}', "g");
  111. inputHoursParse = inputHoursParse.replace(tempRegex,' ');
  112. }
  113. }
  114. }
  115.  
  116. // replace any periods between hours with colons
  117. inputHoursParse = inputHoursParse.replace(/(\d{1,2})\.(\d{2})/g, '$1:$2');
  118. // remove remaining periods
  119. inputHoursParse = inputHoursParse.replace(/\./g, '');
  120. // remove any non-hour colons between letters and numbers and on string ends
  121. inputHoursParse = inputHoursParse.replace(/(\D+)\:(\D+)/g, '$1 $2').replace(/^ *\:/g, ' ').replace(/\: *$/g, ' ');
  122. // replace am/pm with AA/PP
  123. inputHoursParse = inputHoursParse.replace(/ *pm/g,'PP').replace(/ *am/g,'AA');
  124. inputHoursParse = inputHoursParse.replace(/ *p\.m\./g,'PP').replace(/ *a\.m\./g,'AA');
  125. inputHoursParse = inputHoursParse.replace(/ *p\.m/g,'PP').replace(/ *a\.m/g,'AA');
  126. inputHoursParse = inputHoursParse.replace(/ *p/g,'PP').replace(/ *a/g,'AA');
  127. // tighten up dashes
  128. inputHoursParse = inputHoursParse.replace(/\- {1,}/g,'-').replace(/ {1,}\-/g,'-');
  129. inputHoursParse = inputHoursParse.replace(/^(00:00-00:00)$/g,'MM-UU$1');
  130.  
  131. // Change all MTWRFSU to doubles, if any other letters return false
  132. if (inputHoursParse.match(/[bcdeghijklnoqvxyz]/g) !== null) {
  133. returnVal.parseError = true;
  134. return returnVal;
  135. } else {
  136. inputHoursParse = inputHoursParse.replace(/m/g,'MM').replace(/t/g,'TT').replace(/w/g,'WW').replace(/r/g,'RR');
  137. inputHoursParse = inputHoursParse.replace(/f/g,'FF').replace(/s/g,'SS').replace(/u/g,'UU');
  138. }
  139.  
  140. // tighten up spaces
  141. inputHoursParse = inputHoursParse.replace(/ {2,}/g,' ');
  142. inputHoursParse = inputHoursParse.replace(/ {1,}AA/g,'AA');
  143. inputHoursParse = inputHoursParse.replace(/ {1,}PP/g,'PP');
  144. // Expand hours into XX:XX format
  145. for (var asdf=0; asdf<5; asdf++) { // repeat a few times to catch any skipped regex matches
  146. inputHoursParse = inputHoursParse.replace(/([^0-9\:])(\d{1})([^0-9\:])/g, '$10$2:00$3');
  147. inputHoursParse = inputHoursParse.replace(/^(\d{1})([^0-9\:])/g, '0$1:00$2');
  148. inputHoursParse = inputHoursParse.replace(/([^0-9\:])(\d{1})$/g, '$10$2:00');
  149.  
  150. inputHoursParse = inputHoursParse.replace(/([^0-9\:])(\d{2})([^0-9\:])/g, '$1$2:00$3');
  151. inputHoursParse = inputHoursParse.replace(/^(\d{2})([^0-9\:])/g, '$1:00$2');
  152. inputHoursParse = inputHoursParse.replace(/([^0-9\:])(\d{2})$/g, '$1$2:00');
  153.  
  154. inputHoursParse = inputHoursParse.replace(/(\D)(\d{1})(\d{2}\D)/g, '$10$2:$3');
  155. inputHoursParse = inputHoursParse.replace(/^(\d{1})(\d{2}\D)/g, '0$1:$2');
  156. inputHoursParse = inputHoursParse.replace(/(\D)(\d{1})(\d{2})$/g, '$10$2:$3');
  157.  
  158. inputHoursParse = inputHoursParse.replace(/(\D\d{2})(\d{2}\D)/g, '$1:$2');
  159. inputHoursParse = inputHoursParse.replace(/^(\d{2})(\d{2}\D)/g, '$1:$2');
  160. inputHoursParse = inputHoursParse.replace(/(\D\d{2})(\d{2})$/g, '$1:$2');
  161.  
  162. inputHoursParse = inputHoursParse.replace(/(\D)(\d{1}\:)/g, '$10$2');
  163. inputHoursParse = inputHoursParse.replace(/^(\d{1}\:)/g, '0$1');
  164. }
  165.  
  166. // replace 12AM range with 00
  167. inputHoursParse = inputHoursParse.replace( /12(\:\d{2}AA)/g, '00$1');
  168. // Change PM hours to 24hr time
  169. while (inputHoursParse.match(/\d{2}\:\d{2}PP/) !== null) {
  170. tfHourTemp = inputHoursParse.match(/(\d{2})\:\d{2}PP/)[1];
  171. tfHourTemp = parseInt(tfHourTemp) % 12 + 12;
  172. inputHoursParse = inputHoursParse.replace(/\d{2}(\:\d{2})PP/,tfHourTemp.toString()+'$1');
  173. }
  174. // kill the AA
  175. inputHoursParse = inputHoursParse.replace( /AA/g, '');
  176.  
  177. // Side check for tabular input
  178. var inputHoursParseTab = inputHoursParse.replace( /[^A-Z0-9\:-]/g, ' ').replace( / {2,}/g, ' ');
  179. inputHoursParseTab = inputHoursParseTab.replace( /^ +/g, '').replace( / {1,}$/g, '');
  180. if (inputHoursParseTab.match(/[A-Z]{2}\:?\-? [A-Z]{2}\:?\-? [A-Z]{2}\:?\-? [A-Z]{2}\:?\-? [A-Z]{2}\:?\-?/g) !== null) {
  181. inputHoursParseTab = inputHoursParseTab.split(' ');
  182. var reorderThree = [0,7,14,1,8,15,2,9,16,3,10,17,4,11,18,5,12,19,6,13,20];
  183. var reorderTwo = [0,7,1,8,2,9,3,10,4,11,5,12,6,13];
  184. var inputHoursParseReorder = [], reix;
  185. if (inputHoursParseTab.length === 21) {
  186. for (reix=0; reix<21; reix++) {
  187. inputHoursParseReorder.push(inputHoursParseTab[reorderThree[reix]]);
  188. }
  189. } else if (inputHoursParseTab.length === 18) {
  190. for (reix=0; reix<18; reix++) {
  191. inputHoursParseReorder.push(inputHoursParseTab[reorderThree[reix]]);
  192. }
  193. } else if (inputHoursParseTab.length === 15) {
  194. for (reix=0; reix<15; reix++) {
  195. inputHoursParseReorder.push(inputHoursParseTab[reorderThree[reix]]);
  196. }
  197. } else if (inputHoursParseTab.length === 14) {
  198. for (reix=0; reix<14; reix++) {
  199. inputHoursParseReorder.push(inputHoursParseTab[reorderTwo[reix]]);
  200. }
  201. } else if (inputHoursParseTab.length === 12) {
  202. for (reix=0; reix<12; reix++) {
  203. inputHoursParseReorder.push(inputHoursParseTab[reorderTwo[reix]]);
  204. }
  205. } else if (inputHoursParseTab.length === 10) {
  206. for (reix=0; reix<10; reix++) {
  207. inputHoursParseReorder.push(inputHoursParseTab[reorderTwo[reix]]);
  208. }
  209. }
  210.  
  211. if (inputHoursParseReorder.length > 9) {
  212. inputHoursParseReorder = inputHoursParseReorder.join(' ');
  213. inputHoursParseReorder = inputHoursParseReorder.replace(/(\:\d{2}) (\d{2}\:)/g, '$1-$2');
  214. inputHoursParse = inputHoursParseReorder;
  215. }
  216.  
  217. }
  218.  
  219.  
  220. // remove colons after Days field
  221. inputHoursParse = inputHoursParse.replace(/(\D+)\:/g, '$1 ');
  222.  
  223. // Find any double sets
  224. inputHoursParse = inputHoursParse.replace(/([A-Z \-]{2,}) *(\d{2}\:\d{2} *\-{1} *\d{2}\:\d{2}) *(\d{2}\:\d{2} *\-{1} *\d{2}\:\d{2})/g, '$1$2$1$3');
  225. inputHoursParse = inputHoursParse.replace(/(\d{2}\:\d{2}) *(\d{2}\:\d{2})/g, '$1-$2');
  226.  
  227. // remove all spaces
  228. inputHoursParse = inputHoursParse.replace( / */g, '');
  229.  
  230. // Remove any dashes acting as Day separators for 3+ days ("M-W-F")
  231. inputHoursParse = inputHoursParse.replace( /([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})/g, '$1$2$3$4$5$6$7');
  232. inputHoursParse = inputHoursParse.replace( /([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})/g, '$1$2$3$4$5$6');
  233. inputHoursParse = inputHoursParse.replace( /([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})/g, '$1$2$3$4$5');
  234. inputHoursParse = inputHoursParse.replace( /([A-Z]{2})-([A-Z]{2})-([A-Z]{2})-([A-Z]{2})/g, '$1$2$3$4');
  235. inputHoursParse = inputHoursParse.replace( /([A-Z]{2})-([A-Z]{2})-([A-Z]{2})/g, '$1$2$3');
  236.  
  237. // parse any 'through' type terms on the day ranges (MM-RR --> MMTTWWRR)
  238. while (inputHoursParse.match(/[A-Z]{2}\-[A-Z]{2}/) !== null) {
  239. tfDaysTemp = inputHoursParse.match(/([A-Z]{2})\-([A-Z]{2})/);
  240. var startDayIX = this.DAY_CODE_VECTOR.indexOf(tfDaysTemp[1]);
  241. newDayCodeVec = [tfDaysTemp[1]];
  242. for (var dcvix=startDayIX+1; dcvix<startDayIX+7; dcvix++) {
  243. newDayCodeVec.push(this.DAY_CODE_VECTOR[dcvix]);
  244. if (tfDaysTemp[2] === this.DAY_CODE_VECTOR[dcvix]) {
  245. break;
  246. }
  247. }
  248. newDayCodeVec = newDayCodeVec.join('');
  249. inputHoursParse = inputHoursParse.replace(/[A-Z]{2}\-[A-Z]{2}/,newDayCodeVec);
  250. }
  251.  
  252. // split the string between numerical and letter characters
  253. inputHoursParse = inputHoursParse.replace(/([A-Z])\-?\:?([0-9])/g,'$1|$2');
  254. inputHoursParse = inputHoursParse.replace(/([0-9])\-?\:?([A-Z])/g,'$1|$2');
  255. inputHoursParse = inputHoursParse.replace(/(\d{2}\:\d{2})\:00/g,'$1'); // remove seconds
  256. inputHoursParse = inputHoursParse.split("|");
  257.  
  258. var daysVec = [], hoursVec = [];
  259. for (tsix=0; tsix<inputHoursParse.length; tsix++) {
  260. if (inputHoursParse[tsix][0].match(/[A-Z]/) !== null) {
  261. daysVec.push(inputHoursParse[tsix]);
  262. } else if (inputHoursParse[tsix][0].match(/[0-9]/) !== null) {
  263. hoursVec.push(inputHoursParse[tsix]);
  264. } else {
  265. returnVal.parseError = true;
  266. return returnVal;
  267. }
  268. }
  269.  
  270. // check that the dayArray and hourArray lengths correspond
  271. if ( daysVec.length !== hoursVec.length ) {
  272. returnVal.parseError = true;
  273. return returnVal;
  274. }
  275.  
  276. // Combine days with the same hours in the same vector
  277. var newDaysVec = [], newHoursVec = [], hrsIX;
  278. for (tsix=0; tsix<daysVec.length; tsix++) {
  279. if (hoursVec[tsix] !== '99:99-99:99') { // Don't add the closed days
  280. hrsIX = newHoursVec.indexOf(hoursVec[tsix]);
  281. if (hrsIX > -1) {
  282. newDaysVec[hrsIX] = newDaysVec[hrsIX] + daysVec[tsix];
  283. } else {
  284. newDaysVec.push(daysVec[tsix]);
  285. newHoursVec.push(hoursVec[tsix]);
  286. }
  287. }
  288. }
  289.  
  290. const hoursObjectArray = [];
  291. const hoursObjectArrayMinDay = [];
  292. const hoursObjectArraySorted = [];
  293. let hoursObjectAdd;
  294. let daysObjArray;
  295. let toFromSplit;
  296. for (tsix=0; tsix<newDaysVec.length; tsix++) {
  297. hoursObjectAdd = {};
  298. daysObjArray = [];
  299. toFromSplit = newHoursVec[tsix].match(/(\d{2}\:\d{2})\-(\d{2}\:\d{2})/);
  300. if (toFromSplit === null) {
  301. returnVal.parseError = true;
  302. return returnVal;
  303. } else { // Check for hours outside of 0-23 and 0-59
  304. var hourCheck = toFromSplit[1].match(/(\d{2})\:/)[1];
  305. if (hourCheck>23 || hourCheck < 0) {
  306. returnVal.parseError = true;
  307. return returnVal;
  308. }
  309. hourCheck = toFromSplit[2].match(/(\d{2})\:/)[1];
  310. if (hourCheck>23 || hourCheck < 0) {
  311. returnVal.parseError = true;
  312. return returnVal;
  313. }
  314. hourCheck = toFromSplit[1].match(/\:(\d{2})/)[1];
  315. if (hourCheck>59 || hourCheck < 0) {
  316. returnVal.parseError = true;
  317. return returnVal;
  318. }
  319. hourCheck = toFromSplit[2].match(/\:(\d{2})/)[1];
  320. if (hourCheck>59 || hourCheck < 0) {
  321. returnVal.parseError = true;
  322. return returnVal;
  323. }
  324. }
  325. // Make the days object
  326. if ( newDaysVec[tsix].indexOf('MM') > -1 ) {
  327. daysObjArray.push(1);
  328. }
  329. if ( newDaysVec[tsix].indexOf('TT') > -1 ) {
  330. daysObjArray.push(2);
  331. }
  332. if ( newDaysVec[tsix].indexOf('WW') > -1 ) {
  333. daysObjArray.push(3);
  334. }
  335. if ( newDaysVec[tsix].indexOf('RR') > -1 ) {
  336. daysObjArray.push(4);
  337. }
  338. if ( newDaysVec[tsix].indexOf('FF') > -1 ) {
  339. daysObjArray.push(5);
  340. }
  341. if ( newDaysVec[tsix].indexOf('SS') > -1 ) {
  342. daysObjArray.push(6);
  343. }
  344. if ( newDaysVec[tsix].indexOf('UU') > -1 ) {
  345. daysObjArray.push(0);
  346. }
  347. // build the hours object
  348. hoursObjectAdd.fromHour = toFromSplit[1];
  349. hoursObjectAdd.toHour = toFromSplit[2];
  350. hoursObjectAdd.days = daysObjArray.sort();
  351. hoursObjectArray.push(new this.OpeningHours(hoursObjectAdd));
  352. // track the order
  353. if (hoursObjectAdd.days.length > 1 && hoursObjectAdd.days[0] === 0) {
  354. hoursObjectArrayMinDay.push( hoursObjectAdd.days[1] * 100 + parseInt(toFromSplit[1][0])*10 + parseInt(toFromSplit[1][1]) );
  355. } else {
  356. hoursObjectArrayMinDay.push( (((hoursObjectAdd.days[0]+6)%7)+1) * 100 + parseInt(toFromSplit[1][0])*10 + parseInt(toFromSplit[1][1]) );
  357. }
  358. }
  359. this._sortWithIndex(hoursObjectArrayMinDay);
  360. for (var hoaix=0; hoaix < hoursObjectArrayMinDay.length; hoaix++) {
  361. hoursObjectArraySorted.push(hoursObjectArray[hoursObjectArrayMinDay.sortIndices[hoaix]]);
  362. }
  363. if ( !this._checkHours(hoursObjectArraySorted) ) {
  364. returnVal.hours = hoursObjectArraySorted;
  365. returnVal.overlappingHours = true;
  366. return returnVal;
  367. } else if ( this._hasSameOpenCloseTimes(hoursObjectArraySorted) ) {
  368. returnVal.hours = hoursObjectArraySorted;
  369. returnVal.sameOpenAndCloseTimes = true;
  370. return returnVal;
  371. } else {
  372. for ( var ohix=0; ohix<hoursObjectArraySorted.length; ohix++ ) {
  373. if ( hoursObjectArraySorted[ohix].days.length === 2 && hoursObjectArraySorted[ohix].days[0] === 0 && hoursObjectArraySorted[ohix].days[1] === 1) {
  374. // separate hours
  375. hoursObjectArraySorted.push(new this.OpeningHours({days: [0], fromHour: hoursObjectArraySorted[ohix].fromHour, toHour: hoursObjectArraySorted[ohix].toHour}));
  376. hoursObjectArraySorted[ohix].days = [1];
  377. }
  378. }
  379. }
  380. returnVal.hours = hoursObjectArraySorted;
  381. return returnVal;
  382. }
  383.  
  384. // function to check overlapping hours
  385. _checkHours(hoursObj) {
  386. if (hoursObj.length === 1) {
  387. return true;
  388. }
  389. var daysObj, fromHourTemp, toHourTemp;
  390. for (var day2Ch=0; day2Ch<7; day2Ch++) { // Go thru each day of the week
  391. daysObj = [];
  392. for ( var hourSet = 0; hourSet < hoursObj.length; hourSet++ ) { // For each set of hours
  393. if (hoursObj[hourSet].days.indexOf(day2Ch) > -1) { // pull out hours that are for the current day, add 2400 if it goes past midnight, and store
  394. fromHourTemp = hoursObj[hourSet].fromHour.replace(/\:/g,'');
  395. toHourTemp = hoursObj[hourSet].toHour.replace(/\:/g,'');
  396. if (toHourTemp <= fromHourTemp) {
  397. toHourTemp = parseInt(toHourTemp) + 2400;
  398. }
  399. daysObj.push([fromHourTemp, toHourTemp]);
  400. }
  401. }
  402. if (daysObj.length > 1) { // If there's multiple hours for the day, check them for overlap
  403. for ( var hourSetCheck2 = 1; hourSetCheck2 < daysObj.length; hourSetCheck2++ ) {
  404. for ( var hourSetCheck1 = 0; hourSetCheck1 < hourSetCheck2; hourSetCheck1++ ) {
  405. if ( daysObj[hourSetCheck2][0] > daysObj[hourSetCheck1][0] && daysObj[hourSetCheck2][0] < daysObj[hourSetCheck1][1] ) {
  406. return false;
  407. }
  408. if ( daysObj[hourSetCheck2][1] > daysObj[hourSetCheck1][0] && daysObj[hourSetCheck2][1] < daysObj[hourSetCheck1][1] ) {
  409. return false;
  410. }
  411. }
  412. }
  413. }
  414. }
  415. return true;
  416. }
  417.  
  418. _hasSameOpenCloseTimes(hoursObj) {
  419. var fromHourTemp, toHourTemp;
  420. for ( var hourSet = 0; hourSet < hoursObj.length; hourSet++ ) { // For each set of hours
  421. fromHourTemp = hoursObj[hourSet].fromHour;
  422. toHourTemp = hoursObj[hourSet].toHour;
  423. if (fromHourTemp !== '00:00' && fromHourTemp === toHourTemp) {
  424. // If open and close times are the same, don't parse.
  425. return true;
  426. }
  427. }
  428. return false;
  429. }
  430.  
  431. _sortWithIndex(toSort) {
  432. for (var i = 0; i < toSort.length; i++) {
  433. toSort[i] = [toSort[i], i];
  434. }
  435. toSort.sort(function(left, right) {
  436. return left[0] < right[0] ? -1 : 1;
  437. });
  438. toSort.sortIndices = [];
  439. for (var j = 0; j < toSort.length; j++) {
  440. toSort.sortIndices.push(toSort[j][1]);
  441. toSort[j] = toSort[j][0];
  442. }
  443. return toSort;
  444. }
  445. }