Skip to content Skip to sidebar Skip to footer

Store Shop Opening Times

This is more of an app design question so forgive me if it's not relevant. The app I am working on is designed to show what shops are open in the area and I am not sure what is the

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"