package net.osmand.osm; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.List; public class OpeningHoursParser { private static final String[] daysStr = new String[] {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ public static interface OpeningHoursRule { public boolean isOpenedForTime(Calendar cal); public String toRuleString(); } public static class BasicDayOpeningHourRule implements OpeningHoursRule { private boolean[] days = new boolean[7]; private int startTime = -1; private int endTime = - 1; public boolean[] getDays() { return days; } public void setStartTime(int startTime) { this.startTime = startTime; } public int getStartTime() { return startTime; } public int getEndTime() { return endTime; } public void setEndTime(int endTime) { this.endTime = endTime; } @Override public boolean isOpenedForTime(Calendar cal) { if(startTime == -1){ return false; } int i = cal.get(Calendar.DAY_OF_WEEK); int d = (i + 5) % 7; int p = d - 1; if(p < 0){ p+=7; } int time = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE); // one day working 10 - 20 (not 20 - 04) if(startTime < endTime || endTime == -1){ if(days[d]){ if(time >= startTime && (endTime == -1 || time <= endTime)){ return true; } } return false; } else { if (time >= startTime && days[p]) { // check in previous day return true; } else if (time <= endTime && days[d]) { // check in previous day return true; } return false; } } @Override public String toRuleString() { StringBuilder b = new StringBuilder(25); boolean dash = false; boolean first = true; boolean open24_7 = true; for(int i=0; i< 7; i++){ if (days[i]) { if (i > 0 && days[i - 1] && i < 6 && days[i + 1]) { if (!dash) { dash = true; b.append("-"); //$NON-NLS-1$ } continue; } if (first) { first = false; } else if (!dash) { b.append(", "); //$NON-NLS-1$ } b.append(daysStr[i]); dash = false; } else { open24_7 = false; } } if(open24_7 && startTime == 0 && endTime / 60 == 24){ return "24/7"; } int stHour = startTime / 60; int stTime = startTime - stHour * 60; int enHour = endTime / 60; int enTime = endTime - enHour * 60; b.append(" "); //$NON-NLS-1$ formatTime(stHour, stTime, b); b.append("-"); //$NON-NLS-1$ formatTime(enHour, enTime, b); return b.toString(); } @Override public String toString() { return toRuleString(); } } public static OpeningHoursRule parseRule(String r){ int startDay = -1; int previousDay = -1; int k = 0; // check 24/7 BasicDayOpeningHourRule basic = new BasicDayOpeningHourRule(); boolean[] days = basic.getDays(); if("24/7".equals(r)){ Arrays.fill(days, true); basic.setStartTime(0); basic.setEndTime(24*60); return basic; } for (; k < r.length(); k++) { char ch = r.charAt(k); if (Character.isDigit(ch)) { // time starts break; } if(Character.isWhitespace(ch) || ch == ','){ continue; } else if(ch == '-'){ if(previousDay != -1){ startDay = previousDay; } else { return null; } } else if(k < r.length() - 1){ int i = 0; for(String s : daysStr){ if(s.charAt(0) == ch && s.charAt(1) == r.charAt(k+1)){ break; } i++; } if(i < daysStr.length){ if(startDay != -1){ for (int j = startDay; j <= i; j++) { days[j] = true; } startDay = -1; } else { days[i] = true; } previousDay = i; } } else { return null; } } if(previousDay == -1){ return null; } String time = r.substring(k); String[] stEnd = time.split("-"); //$NON-NLS-1$ if(stEnd.length != 2){ return null; } int st; int end; try { int i1 = stEnd[0].indexOf(':'); int i2 = stEnd[1].indexOf(':'); if(i1 == -1 || i2 == -1){ return null; } st = Integer.parseInt(stEnd[0].substring(0, i1).trim())* 60 + Integer.parseInt(stEnd[0].substring(i1 + 1).trim()); end = Integer.parseInt(stEnd[1].substring(0, i2).trim())* 60 + Integer.parseInt(stEnd[1].substring(i2 + 1).trim()); } catch (NumberFormatException e) { return null; } basic.setStartTime(st); basic.setEndTime(end); return basic; } public static List<OpeningHoursRule> parseOpenedHours(String format){ String[] rules = format.split(";"); //$NON-NLS-1$ List<OpeningHoursRule> rs = new ArrayList<OpeningHoursRule>(); for(String r : rules){ r = r.trim(); if(r.length() == 0){ continue; } // check if valid OpeningHoursRule rule = parseRule(r); if(rule == null){ return null; } rs.add(rule); } return rs; } public static String toStringOpenedHours(List<? extends OpeningHoursRule> rules){ StringBuilder b = new StringBuilder(100); // check 24/7 boolean first = true; for (OpeningHoursRule p : rules) { if(p == null){ continue; } if (first) { first = false; } else { b.append("; "); //$NON-NLS-1$ } b.append(p.toRuleString()); } return b.toString(); } private static void formatTime(int h, int t, StringBuilder b){ if(h < 10){ b.append("0"); //$NON-NLS-1$ } b.append(h).append(":"); //$NON-NLS-1$ if(t < 10){ b.append("0"); //$NON-NLS-1$ } b.append(t); } public static void main(String[] args) { List<OpeningHoursRule> hours = parseOpenedHours("Mo-Fr 08:30-14:40; Sa 08:00 - 14:00"); //$NON-NLS-1$ System.out.println(hours); System.out.println(toStringOpenedHours(hours)); hours = parseOpenedHours("Mo, We-Fr, Th, Sa 08:30-14:40; Sa 08:00 - 14:00"); //$NON-NLS-1$ System.out.println(hours); System.out.println(toStringOpenedHours(hours)); hours = parseOpenedHours("Mo-Su 00:00-24:00"); //$NON-NLS-1$ System.out.println(hours); System.out.println(toStringOpenedHours(hours)); hours = parseOpenedHours("24/7"); //$NON-NLS-1$ System.out.println(hours); System.out.println(toStringOpenedHours(hours)); } }