Store Shop Opening Times
Solution 1:
I assume your DB looks like this:
("Bob's Bakery", [0,0,1,1,1,1, ... ])
("Aunt McGee's Gun-O-Rama", [0,0,0,0,1,1, ... ])
....
In my example above I define that the bit-array starts at 07:00 AM. The "..." express my lazyness to continue until 12:00 PM :)
You could populate a hash map with that data, so you end up with a mapping of "start-of-15-min-slot" to "open shop". something like this (simple pseudo code to visualize my idea):
openShops = {
("07:30",{"Bob's Bakery"}),
("07:45",{"Bob's Bakery"}),
("08:00",{"Bob's Bakery","Aunt McGee's Gun-O-Rama"}),
("08:15",{"Bob's Bakery","Aunt McGee's Gun-O-Rama"}),
...
}
This way you only have to calculate the beginning of the current 15 min slot and perform one look-up. Let's says you want to open shops for 08:02, then you just have to divide the minutes by 15 (without remainder) and use the result as the value for the minutes in the query:
2 div 15 = 0 → 08:00 → openShops.get("08:00")
→ ("Bob's Bakery","Aunt McGee's Gun-O-Rama")
Solution 2:
I will ignore the database side, as you claim to be getting an array of boolean primitive values from the array.
Enum, EnumSet, EnumMap
On the Java side, you can use the surprisingly powerful enum facility in Java along with an EnumSet
.
Define an enum for all the time slots. I'll include only a few for brevity. I add a displayName
for a prettier label for each enum item.
enum QuarterHour {
T_0700_0715, T_0715_0730, T_0730_0745, T_0745_0800;
public String displayName;
public LocalTime start, stop;
private QuarterHour () {
// Soft-code the members of each enum item by parsing its name.this.displayName = this.name ().replace ( "T_" , "" ).replace ( "_" , "-" );
String[] tokens = this.displayName.split ( "-" ); // Extract the start and stop times from the left and right parts of this string.
String t1 = tokens[ 0 ].substring ( 0 , 2 ) + ":" + tokens[ 0 ].substring ( 2 );
String t2 = tokens[ 1 ].substring ( 0 , 2 ) + ":" + tokens[ 1 ].substring ( 2 );
this.start = LocalTime.parse ( t1 );
this.stop = LocalTime.parse ( t2 );
System.out.println ( "Debug construction of each QuarterHour enum item: " + this.name () + " with displayName: " + this.displayName + " from " + this.start + " to " + this.stop );
}
}
Java offers the very fast and very small EnumSet
and EnumMap
classes to collect Enum
instances. Each is respectively an implementation of Set
and Map
like any other implementation. What is special is that because they are dedicated to Enum
instances, they can be highly optimized by using bitmaps internally. So they use very little memory and execute extremely quickly.
Ignoring your boolean array for a moment, here is some example code showing how to use the EnumSet
and EnumMap
.
DayOfWeek
Our map uses the built-in DayOfWeek
enum that represents each of the seven days of the week, Monday-Sunday.
java.time
The DayOfWeek
enum is part of the java.time framework built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date
. See Oracle Tutorial. Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.
Example code
In this example I have the weekdays opening the full hour 07:00 to 08:00 (four quarter-hours) and the weekend opening a half-hour later 07:30 to 08:00 (two quarter-hours).
EnumMap<DayOfWeek , EnumSet<QuarterHour>> days = newEnumMap<> ( DayOfWeek.class );
EnumSetquarterHoursWhenOpen= EnumSet.of ( QuarterHour.T_0700_0715 , QuarterHour.T_0715_0730 , QuarterHour.T_0730_0745 , QuarterHour.T_0745_0800 );
EnumSetquarterHoursWhenOpen2= EnumSet.of ( QuarterHour.T_0730_0745 , QuarterHour.T_0745_0800 );
days.put ( DayOfWeek.MONDAY , quarterHoursWhenOpen );
days.put ( DayOfWeek.TUESDAY , quarterHoursWhenOpen );
days.put ( DayOfWeek.WEDNESDAY , quarterHoursWhenOpen );
days.put ( DayOfWeek.THURSDAY , quarterHoursWhenOpen );
days.put ( DayOfWeek.FRIDAY , quarterHoursWhenOpen );
days.put ( DayOfWeek.SATURDAY , quarterHoursWhenOpen2 );
days.put ( DayOfWeek.SUNDAY , quarterHoursWhenOpen2 );
Dump to console. By default the toString
method being implicitly called on our QuarterHours
enum by default uses the name of the element. For presentation to your users you would call the displayName
method I defined rather than call the built-in toString
. That toString
method is defined as being intended for "programmer-friendly" string values rather than user-oriented presentation strings.
System.out.println ( "days: " + days );
days: {MONDAY=[T_0700_0715, T_0715_0730, T_0730_0745, T_0745_0800], TUESDAY=[T_0700_0715, T_0715_0730, T_0730_0745, T_0745_0800], WEDNESDAY=[T_0700_0715, T_0715_0730, T_0730_0745, T_0745_0800], THURSDAY=[T_0700_0715, T_0715_0730, T_0730_0745, T_0745_0800], FRIDAY=[T_0700_0715, T_0715_0730, T_0730_0745, T_0745_0800], SATURDAY=[T_0730_0745, T_0745_0800], SUNDAY=[T_0730_0745, T_0745_0800]}
By the way, this naming of start-stop times follows the common approach in handling spans of time called "Half-Open" where the start is inclusive while the ending is exclusive.
Conversion
All we have left to do is convert back-and-forth to/from EnumSet QuarterHours
and boolean array. For more information, see my Question: Convert between EnumSet and array of boolean values. Here I use the simple for
loop approach, but look at the other answers for the more compact Lambda & streams syntax available in Java 8 and later.
The following code calls the values
method on an enum. This method is annoyingly not documented on the Enum
class because the method is synthetically created by the compiler for tricky internal technicalities as discussed in this Question. The upshot is that the method returns an array of all the items in the enum.
Caveat: All this code is untested, only run this once. Use at your own risk.
From EnumSet to array
// From EnumSet to array of boolean primitives.
QuarterHour[] quarterHoursOfDay = QuarterHour.values ();
boolean[] quarterHoursIfOpen = newboolean[ quarterHoursOfDay.length ];
EnumSet<QuarterHour> enumSet = days.get ( DayOfWeek.SATURDAY );
for ( int i = 0 ; i < quarterHoursOfDay.length ; i ++ ) {
quarterHoursIfOpen[ i ] = enumSet.contains ( quarterHoursOfDay[ i ] );
}
Dump to console.
System.out.println ( "For " + DayOfWeek.SATURDAY + " array quarterHoursIfOpen: " + Arrays.toString ( quarterHoursIfOpen ) );
For SATURDAY array quarterHoursIfOpen: [false, false, true, true]
From array to EnumSet
Going the other direction, from the array of boolean quarterHoursIfOpen
above to a fresh EnumSet
named enumSet2
below.
// From array of boolean to EnumSet.
EnumSet<QuarterHour> enumSet2 = EnumSet.noneOf ( QuarterHour.class );
QuarterHour[] quarterHoursOfDay2 = QuarterHour.values ();
for ( int i = 0 ; i < quarterHoursOfDay2.length ; i ++ ) {
boolean isOpen = quarterHoursIfOpen[ i ];
if ( isOpen ) {
enumSet2.add ( quarterHoursOfDay[ i ] );
}
}
Dump to console.
System.out.println ( "enumSet2: " + enumSet2 );
enumSet2: [T_0730_0745, T_0745_0800]
Generate source code
Here is some source code to generate source code to name all 24-hours worth of quarter hour enum names.
StringBuilderenums=newStringBuilder ();
LocalTimestart= LocalTime.MIN;
for ( inti=0 ; i < ( 24 * 4 ) ; i ++ ) {
if ( enums.length () > 0 ) {
enums.append ( " , " );
}
LocalTimestop= start.plusMinutes ( 15 );
Stringname="T_" + start.toString () + "_" + stop.toString ();
name = name.replaceAll ( ":" , "" );
enums.append ( name );
// Setup next loop
start = stop;
}
System.out.println ( "enums: " + enums );
enums: T_0000_0015 , T_0015_0030 , T_0030_0045 , T_0045_0100 , T_0100_0115 , T_0115_0130 , T_0130_0145 , T_0145_0200 , T_0200_0215 , T_0215_0230 , T_0230_0245 , T_0245_0300 , T_0300_0315 , T_0315_0330 , T_0330_0345 , T_0345_0400 , T_0400_0415 , T_0415_0430 , T_0430_0445 , T_0445_0500 , T_0500_0515 , T_0515_0530 , T_0530_0545 , T_0545_0600 , T_0600_0615 , T_0615_0630 , T_0630_0645 , T_0645_0700 , T_0700_0715 , T_0715_0730 , T_0730_0745 , T_0745_0800 , T_0800_0815 , T_0815_0830 , T_0830_0845 , T_0845_0900 , T_0900_0915 , T_0915_0930 , T_0930_0945 , T_0945_1000 , T_1000_1015 , T_1015_1030 , T_1030_1045 , T_1045_1100 , T_1100_1115 , T_1115_1130 , T_1130_1145 , T_1145_1200 , T_1200_1215 , T_1215_1230 , T_1230_1245 , T_1245_1300 , T_1300_1315 , T_1315_1330 , T_1330_1345 , T_1345_1400 , T_1400_1415 , T_1415_1430 , T_1430_1445 , T_1445_1500 , T_1500_1515 , T_1515_1530 , T_1530_1545 , T_1545_1600 , T_1600_1615 , T_1615_1630 , T_1630_1645 , T_1645_1700 , T_1700_1715 , T_1715_1730 , T_1730_1745 , T_1745_1800 , T_1800_1815 , T_1815_1830 , T_1830_1845 , T_1845_1900 , T_1900_1915 , T_1915_1930 , T_1930_1945 , T_1945_2000 , T_2000_2015 , T_2015_2030 , T_2030_2045 , T_2045_2100 , T_2100_2115 , T_2115_2130 , T_2130_2145 , T_2145_2200 , T_2200_2215 , T_2215_2230 , T_2230_2245 , T_2245_2300 , T_2300_2315 , T_2315_2330 , T_2330_2345 , T_2345_0000
Post a Comment for "Store Shop Opening Times"