<p>This is a nasty one for me...  I'm a PHP guy working in Java on a JSP project.  I know how to do what I'm attempting through too much code and a complete lack of finesse.   </p>

<p>I'd prefer to do it right. Here is the situation:</p>

<p>I'm writing a small display to show customers what days they can water their lawns based on their watering group (ABCDE) and what time of year it is.  Our seasons look like this:
Summer (5-1 to 8-31) 
Spring  (3-1 to 4-30) 
Fall (9-1 to 10-31)
Winter (11-1 to 2-28) </p>

<p>An example might be:</p>

<p>If I'm in group A, here would be my allowed times:
Winter: Mondays only
Spring: Tues, Thurs, Sat
Summer: Any Day
Fall: Tues, Thurs, Sat</p>

<p>If I was writing this in PHP I would use arrays like this:</p>

<pre><code>//M=Monday,t=Tuesday,T=Thursday.... etc
$schedule["A"]["Winter"]='M';
$schedule["A"]["Spring"]='tTS';
$schedule["A"]["Summer"]='Any';
$schedule["A"]["Fall"]='tTS';
$schedule["B"]["Winter"]='t';
</code></pre>

<p>I COULD make the days arrays (array("Tuesday","Thursday","Saturday")) etc, but it is not necessary for what I'm really trying to accomplish.</p>

<p>I will also need to setup arrays to determine what season I'm in:</p>

<pre><code>$seasons["Summer"]["start"]=0501;
$seasons["Summer"]["end"]=0801;
</code></pre>

<p>Can anyone suggest a really cool way to do this? I will have today's date and the group letter.  I will need to get out of my function a day (M) or a series of days (tTS), (Any).</p>

[{'answer_id': 12878, 'author': 'Mike Stone', 'author_id': 122, 'author_profile': 'https://Stackoverflow.com/users/122', 'pm_score': 5, 'selected': True, 'text': '<p>You could do essentially the same code with Hashtables (or some other Map):</p>\n\n<pre><code>Hashtable&lt;String, Hashtable&lt;String, String&gt;&gt; schedule\n    = new Hashtable&lt;String, Hashtable&lt;String, String&gt;&gt;();\nschedule.put("A", new Hashtable&lt;String, String&gt;());\nschedule.put("B", new Hashtable&lt;String, String&gt;());\nschedule.put("C", new Hashtable&lt;String, String&gt;());\nschedule.put("D", new Hashtable&lt;String, String&gt;());\nschedule.put("E", new Hashtable&lt;String, String&gt;());\n\nschedule.get("A").put("Winter", "M");\nschedule.get("A").put("Spring", "tTS");\n// Etc...\n</code></pre>\n\n<p>Not as elegant, but then again, Java isn\'t a dynamic language, and it doesn\'t have hashes on the language level.</p>\n\n<p>Note: You might be able to do a better solution, this just popped in my head as I read your question.</p>\n'}, {'answer_id': 12885, 'author': 'Derek Park', 'author_id': 872, 'author_profile': 'https://Stackoverflow.com/users/872', 'pm_score': 0, 'selected': False, 'text': '<p>There is no pretty solution.  Java just doesn\'t do things like this well.  Mike\'s solution is pretty much the way to do it if you want strings as the indices (keys).  Another option if the hash-of-hashes setup is too ugly is to append the strings together (shamelessly stolen from Mike and modified):</p>\n\n<pre><code>Hashtable&lt;String, String&gt; schedule = new Hashtable&lt;String, String&gt;();\nschedule.put("A-Winter", "M");\nschedule.put("A-Spring", "tTS");\n</code></pre>\n\n<p>and then lookup:</p>\n\n<pre><code>String val = schedule.get(group + "-" + season);\n</code></pre>\n\n<p>If you\'re unhappy with the general ugliness (and I don\'t blame you), put it all behind a method call:</p>\n\n<pre><code>String whenCanIWater(String group, Date date) { /* ugliness here */ }\n</code></pre>\n'}, {'answer_id': 12899, 'author': 'Wing', 'author_id': 958, 'author_profile': 'https://Stackoverflow.com/users/958', 'pm_score': 2, 'selected': False, 'text': '<p>I\'m not a Java programmer, but getting away from Java and just thinking in terms that are more language agnostic - a cleaner way to do it might be to use either constants or enumerated types.  This should work in any langauge that supports multi-dimensional arrays.</p>\n\n<p>If using named constants, where, for example: </p>\n\n<pre><code>int A = 0;\nint B = 1;\nint C = 2;\nint D = 3;\n\nint Spring = 0; \nint Summer = 1;\nint Winter = 2; \nint Fall = 3;\n...\n</code></pre>\n\n<p>Then the constants serve as more readable array subscripts:</p>\n\n<pre><code>schedule[A][Winter]="M";\nschedule[A][Spring]="tTS";\nschedule[A][Summer]="Any";\nschedule[A][Fall]="tTS";\nschedule[B][Winter]="t";\n</code></pre>\n\n<p>Using enumerated types:</p>\n\n<pre><code>enum groups\n{\n  A = 0,\n  B = 1,\n  C = 2,\n  D = 3\n}\n\nenum seasons\n{\n  Spring = 0,\n  Summer = 1,\n  Fall = 2,\n  Winter = 3\n}\n...\nschedule[groups.A][seasons.Winter]="M";\nschedule[groups.A][seasons.Spring]="tTS";\nschedule[groups.A][seasons.Summer]="Any";\nschedule[groups.A][seasons.Fall]="tTS";\nschedule[groups.B][seasons.Winter]="t";\n</code></pre>\n'}, {'answer_id': 12918, 'author': 'Vincent Robert', 'author_id': 268, 'author_profile': 'https://Stackoverflow.com/users/268', 'pm_score': 3, 'selected': False, 'text': '<p>Don\'t try to be as dynamic as PHP is. You could try to first <strong>define</strong> what you need.</p>\n\n<pre><code>interface Season\n{\n    public string getDays();\n}\n\ninterface User\n{\n    public Season getWinter();\n    public Season getSpring();\n    public Season getSummer();\n    public Season getFall();\n}\n\ninterface UserMap\n{\n    public User getUser(string name);\n}\n</code></pre>\n\n<p>And please, read the documentation of <a href="http://java.sun.com/javase/6/docs/api/java/util/Hashtable.html" rel="noreferrer">Hashtable</a> before using it. This class is synchronized which means that each call is protected against multithreading which really slows the access when you don\'t need the extra protection. Please use any <a href="http://java.sun.com/javase/6/docs/api/java/util/Map.html" rel="noreferrer">Map</a> implementation instead like <a href="http://java.sun.com/javase/6/docs/api/java/util/HashMap.html" rel="noreferrer">HashMap</a> or <a href="http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html" rel="noreferrer">TreeMap</a>.</p>\n'}, {'answer_id': 12923, 'author': 'Ian Good', 'author_id': 1195, 'author_profile': 'https://Stackoverflow.com/users/1195', 'pm_score': 3, 'selected': False, 'text': "<p>It seems like everyone is trying to find the Java way to do it like you're doing it in PHP, instead of the way it ought to be done in Java. Just consider each piece of your array an object, or, at the very least, the first level of the array as an object and each sub level as variables inside the object. The build a data structure that you populate with said objects and access the objects through the data structure's given accessors.</p>\n\n<p>Something like:</p>\n\n<pre><code>class Schedule\n{\n  private String group;\n  private String season;\n  private String rundays;\n  public Schedule() { this.group = null; this.season = null; this.rundays= null; }\n  public void setGroup(String g) { this.group = g; }\n  public String getGroup() { return this.group; }\n  ...\n}\n\npublic ArrayList&lt;Schedule&gt; schedules = new ArrayList&lt;Schedule&gt;();\nSchedule s = new Schedule();\ns.setGroup(...);\n...\nschedules.add(s);\n...\n</code></pre>\n\n<p>Of course that probably isn't right either. I'd make each season an object, and maybe each weekday list as an object too. Anyway, its more easily reused, understood, and extensible than a hobbled-together Hashtable that tries to imitate your PHP code. Of course, PHP has objects too, and you should use them in a similar fashion instead of your uber-arrays, wherever possible. I do understand the temptation to cheat, though. PHP makes it so easy, and so fun!</p>\n"}, {'answer_id': 12932, 'author': 'Tim Frey', 'author_id': 1471, 'author_profile': 'https://Stackoverflow.com/users/1471', 'pm_score': 1, 'selected': False, 'text': '<p>I agree that you should definitely put this logic behind the clean interface of:</p>\n\n<pre><code>public String lookupDays(String group, String date);\n</code></pre>\n\n<p>but maybe you should stick the data in a properties file.  I\'m not against hardcoding this data in your source files but, as you noticed, Java can be pretty wordy when it comes to nested Collections.  Your file might looks like:</p>\n\n<blockquote>\n  <p>A.Summer=M<br>\n  A.Spring=tTS<br>\n  B.Summer=T</p>\n</blockquote>\n\n<p>Usually I don\'t like to move static data like this to an external file because it increases the "distance" between the data and the code that uses it.  However, whenever you\'re dealing with nested Collections, especially maps, things can get real ugly, real fast.</p>\n\n<p>If you don\'t like this idea, maybe you can do something like this:</p>\n\n<pre><code>public class WaterScheduler\n{\n  private static final Map&lt;String, String&gt; GROUP2SEASON = new HashMap&lt;String, String&gt;();\n  static\n  {\n    addEntry("A", "Summer", "M");\n    addEntry("A", "Spring", "tTS");\n    addEntry("B", "Summer", "T");\n  }\n\n  private static void addEntry(String group, String season, String value)\n  {\n    GROUP2SEASON.put(group + "." + season, value);\n  }\n\n}\n</code></pre>\n\n<p>You lose some readability but at least the data is closer to where it\'s going to be used.</p>\n'}, {'answer_id': 12941, 'author': 'Derek Park', 'author_id': 872, 'author_profile': 'https://Stackoverflow.com/users/872', 'pm_score': 2, 'selected': False, 'text': "<p>I'm totally at a loss as to why some of you seem to think that throwing gobs of objects at the code is the way to go.  For example, there are exactly four seasons, and they don't <em>do</em> or <em>store</em> anything.  How does it simplify anything to make them objects?  Wing is quite right that these should probably be <strong><em>constants</em></strong> (or maybe enums).</p>\n\n<p>What Bruce needs, at it's heart, is simply a lookup table.  He doesn't need a hierarchy of objects and interfaces; he needs a way to look up a schedule based on a season and a group identifier.  Turning things into objects only makes sense if they have responsibilities or state.  If they have neither, then they are simply identifiers, and building special objects for them just makes the codebase larger.</p>\n\n<p>You <em>could</em> build, e.g., <code>Group</code> objects that each contain a set of schedule strings (one for each season), but if all the <code>Group</code> object does is provide lookup functionality, then you've reinvented the lookup table in a much less intuitive fashion.  If he has to look up the group, and then lookup the schedule, all he has is a two-step lookup table that took longer to code, is more likely to be buggy, and will be harder to maintain.</p>\n"}, {'answer_id': 12953, 'author': 'Jason Day', 'author_id': 737, 'author_profile': 'https://Stackoverflow.com/users/737', 'pm_score': 1, 'selected': False, 'text': '<p>A better solution would perhaps be to put all that data into a database, instead of hard-coding it in your sources or using properties files.</p>\n\n<p>Using a database will be much easier to maintain, and there are a <a href="http://www.mysql.com/" rel="nofollow noreferrer">variety</a> <a href="http://www.postgresql.org/" rel="nofollow noreferrer">of</a> <a href="http://hsqldb.sourceforge.net/" rel="nofollow noreferrer">free</a> <a href="http://db.apache.org/derby/" rel="nofollow noreferrer">database</a> engines to choose from.</p>\n\n<p>Two of these database engines are implemented entirely in Java and can be embedded in an application just by including a jar file. It\'s a little heavyweight, sure, but it\'s a lot more scalable and easier to maintain. Just because there are 20 records today doesn\'t mean there won\'t be more later due to changing requirements or feature creep.</p>\n\n<p>If, in a few weeks or months, you decide you want to add, say, time of day watering restrictions, it will be much easier to add that functionality if you\'re already using a database. Even if that never happens, then you\'ve spent a few hours learning how to embed a database in an application.</p>\n'}, {'answer_id': 12992, 'author': 'bpapa', 'author_id': 543, 'author_profile': 'https://Stackoverflow.com/users/543', 'pm_score': 1, 'selected': False, 'text': '<p>Does the "date" have to be a parameter? If you\'re just showing the current watering schedule the WateringSchedule class itself can figure out what day it is, and therefore what season it is. Then just have a method which returns a map where the Key is the group letter. Something like:</p>\n\n<pre><code>public Map&lt;String,List&lt;String&gt;&gt; getGroupToScheduledDaysMap() {\n  // instantiate a date or whatever to decide what Map to return\n}\n</code></pre>\n\n<p>Then in the JSP page</p>\n\n<pre><code>&lt;c:forEach var="day" items="${scheduler.groupToScheduledDaysMap["A"]}"&gt;\n   ${day}\n&lt;/c:forEach&gt;\n</code></pre>\n\n<p>If you need to show the schedules for more than one season, you should have a method in the WateringSchedule class that returns a map where Seasons are the keys, and then Maps of groupToScheduledDays are the values.</p>\n'}, {'answer_id': 13037, 'author': 'Akira', 'author_id': 795, 'author_profile': 'https://Stackoverflow.com/users/795', 'pm_score': 2, 'selected': False, 'text': "<p>Here's one way it <em>could</em> look like, you can figure the rest out:</p>\n\n<pre><code>A = new Group();\nA.getSeason(Seasons.WINTER).addDay(Days.MONDAY);\nA.getSeason(Seasons.SPRING).addDay(Days.TUESDAY).addDay(Days.THURSDAY);\nA.getSeason(Seasons.SPRING).addDays(Days.MONDAY, Days.TUESDAY, ...);\n\nschedule = new Schedule();\nschedule.addWateringGroup( A );\n</code></pre>\n"}, {'answer_id': 13099, 'author': 'McDowell', 'author_id': 304, 'author_profile': 'https://Stackoverflow.com/users/304', 'pm_score': 2, 'selected': False, 'text': "<p>I'm with those that suggest encapsulating function in objects.</p>\n\n<pre><code>import java.util.Date;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class Group {\n\n    private String groupName;\n\n    private Map&lt;Season, Set&lt;Day&gt;&gt; schedule;\n\n    public String getGroupName() {\n        return groupName;\n    }\n\n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n\n    public Map&lt;Season, Set&lt;Day&gt;&gt; getSchedule() {\n        return schedule;\n    }\n\n    public void setSchedule(Map&lt;Season, Set&lt;Day&gt;&gt; schedule) {\n        this.schedule = schedule;\n    }\n\n    public String getScheduleFor(Date date) {\n        Season now = Season.getSeason(date);\n        Set&lt;Day&gt; days = schedule.get(now);\n        return Day.getDaysForDisplay(days);\n    }\n\n}\n</code></pre>\n\n<p>EDIT: Also, your date ranges don't take leap years into account:</p>\n\n<blockquote>\n  <p>Our seasons look like this: Summer\n  (5-1 to 8-31) Spring (3-1 to 4-30)\n  Fall (9-1 to 10-31) Winter (11-1 to\n  2-28)</p>\n</blockquote>\n"}, {'answer_id': 48512739, 'author': 'Basil Bourque', 'author_id': 642706, 'author_profile': 'https://Stackoverflow.com/users/642706', 'pm_score': 0, 'selected': False, 'text': '<h1>tl;dr</h1>\n\n<p>Using modern Java language features and classes, define your own enums to represent the seasons and groups.</p>\n\n<pre><code>Schedule.daysForGroupOnDate( \n    Group.D , \n    LocalDate.now()\n)  \n</code></pre>\n\n<p>That method yields a <code>Set</code> of <code>DayOfWeek</code> enum objects (not mere text!), such as <code>DayOfWeek.TUESDAY</code> &amp; <code>DayOfWeek.THURSDAY</code>.</p>\n\n<h1>Modern Java</h1>\n\n<blockquote>\n  <p>Can anyone suggest a really cool way to do this?</p>\n</blockquote>\n\n<p>Yes.</p>\n\n<p>Modern Java has built-in classes, collections, and enums to help you with this problem.</p>\n\n<p>The <em>java.time</em> framework built into Java offers the <a href="https://docs.oracle.com/javase/9/docs/api/java/time/Month.html" rel="nofollow noreferrer"><code>Month</code></a> enum and <a href="https://docs.oracle.com/javase/9/docs/api/java/time/DayOfWeek.html" rel="nofollow noreferrer"><code>DayOfWeek</code></a> enum. </p>\n\n<p>The <a href="https://docs.oracle.com/javase/9/docs/api/java/util/EnumSet.html" rel="nofollow noreferrer"><code>EnumSet</code></a> and <a href="https://docs.oracle.com/javase/9/docs/api/java/util/EnumMap.html" rel="nofollow noreferrer"><code>EnumMap</code></a> provide implementations of <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Set.html" rel="nofollow noreferrer"><code>Set</code></a> and <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Map.html" rel="nofollow noreferrer"><code>Map</code></a> that are optimized for use with enums for fast execution in very little memory.</p>\n\n<p>You can define your own <a href="https://docs.oracle.com/javase/9/docs/api/java/lang/Enum.html" rel="nofollow noreferrer">enums</a> to represent your season and your groups (A, B, and so on). The enum facility in Java is far more useful and powerful than seen in other languages. If not familiar, see the <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html" rel="nofollow noreferrer"><em>Oracle Tutorial</em></a>. </p>\n\n<p>The simple syntax of defining your own enums actually provides much of the functionality needed to solve this Question, eliminating some complicated coding. New <a href="http://iteratrlearning.com/java9/2016/11/09/java9-collection-factory-methods.html" rel="nofollow noreferrer">literals syntax</a> for sets and maps in the <a href="https://stackoverflow.com/q/43533835/642706">collections factory methods</a> in Java 9 (<a href="http://openjdk.java.net/jeps/269" rel="nofollow noreferrer">JEP 269</a>) makes the code even simpler now.</p>\n\n<p>Here is a complete working app. <strong>Note how little code</strong> there is for algorithms. Defining your own custom enums does most of the heavy-lifting. </p>\n\n<p>One caveat with this app code: It assumes nothing changes in your business definitions, or at least if there is a change you only care about the current rules, “latest is greatest”. If your rules change over time and you need to represent all the past, present, and future versions, I would build a very different app, probably with a database to store the rules. But this  app here solves the Question as asked. </p>\n\n<h2><code>Season</code></h2>\n\n<p>Represent your season as an enum <code>Season</code>. Each season object holds a <a href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html" rel="nofollow noreferrer"><code>List</code></a> of <a href="https://docs.oracle.com/javase/9/docs/api/java/time/Month.html" rel="nofollow noreferrer"><code>Month</code></a> enum objects that define the length of that particular season. The new <a href="https://docs.oracle.com/javase/9/docs/api/java/util/List.html#of-E-" rel="nofollow noreferrer"><code>List.of</code></a> syntax added to Java 9 defines an immutable list in a literals syntax via static factory methods.</p>\n\n<pre><code>package com.basilbourque.watering;\n\nimport java.time.LocalDate;\nimport java.time.Month;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.Set;\n\npublic enum Season\n{\n    SPRING( List.of( Month.MARCH , Month.APRIL ) ),\n    SUMMER( List.of( Month.MAY , Month.JUNE, Month.JULY , Month.AUGUST ) ),\n    FALL( List.of( Month.SEPTEMBER , Month.OCTOBER ) ),\n    WINTER( List.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY ) );\n\n    private List&lt; Month &gt; months;\n\n    // Constructor\n    Season ( List &lt; Month &gt; monthsArg )\n    {\n        this.months = monthsArg;\n    }\n\n    public List &lt; Month &gt; getMonths ( )\n    {\n        return this.months;\n    }\n\n    // For any given month, determine the season.\n    static public Season ofLocalMonth ( Month monthArg )\n    {\n        Season s = null;\n        for ( Season season : EnumSet.allOf( Season.class ) )\n        {\n            if ( season.getMonths().contains( monthArg ) )\n            {\n                s = season;\n                break; // Bail out of this FOR loop.\n            }\n        }\n        return s;\n    }\n\n    // For any given date, determine the season.\n    static public Season ofLocalDate ( LocalDate localDateArg )\n    {\n        Month month = localDateArg.getMonth();\n        Season s = Season.ofLocalMonth( month );\n        return s;\n    }\n\n    // Run `main` for demo/testing.\n    public static void main ( String[] args )\n    {\n        // Dump all these enum objects to console.\n        for ( Season season : EnumSet.allOf( Season.class ) )\n        {\n            System.out.println( "Season: " + season.toString() + " = " + season.getMonths() );\n        }\n    }\n}\n</code></pre>\n\n<h2><code>Group</code></h2>\n\n<p>Represent each grouping of customers’ lawns/yards, (A, B, C, D, E) as an enum named <code>Group</code>. Each of these enum objects holds a <code>Map</code>, mapping a <code>Season</code> enum object to a <code>Set</code> of <code>DayOfWeek</code> enum objects. For example, <code>Group.A</code> in <code>Season.SPRING</code> allows watering on two days, <code>DayOfWeek.TUESDAY</code> &amp; <code>DayOfWeek.THURSDAY</code>.</p>\n\n<pre><code>package com.basilbourque.watering;\n\nimport java.time.DayOfWeek;\nimport java.util.EnumMap;\nimport java.util.EnumSet;\nimport java.util.Map;\nimport java.util.Set;\n\npublic enum Group\n{\n    A(\n            Map.of(\n                    Season.SPRING , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,\n                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,\n                    Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,\n                    Season.WINTER , EnumSet.of( DayOfWeek.TUESDAY )\n            )\n    ),\n    B(\n            Map.of(\n                    Season.SPRING , EnumSet.of( DayOfWeek.FRIDAY ) ,\n                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,\n                    Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.FRIDAY ) ,\n                    Season.WINTER , EnumSet.of( DayOfWeek.FRIDAY )\n            )\n    ),\n    C(\n            Map.of(\n                    Season.SPRING , EnumSet.of( DayOfWeek.MONDAY ) ,\n                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,\n                    Season.FALL , EnumSet.of( DayOfWeek.MONDAY , DayOfWeek.TUESDAY ) ,\n                    Season.WINTER , EnumSet.of( DayOfWeek.MONDAY )\n            )\n    ),\n    D(\n            Map.of(\n                    Season.SPRING , EnumSet.of( DayOfWeek.WEDNESDAY , DayOfWeek.FRIDAY ) ,\n                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,\n                    Season.FALL , EnumSet.of( DayOfWeek.FRIDAY ) ,\n                    Season.WINTER , EnumSet.of( DayOfWeek.WEDNESDAY )\n            )\n    ),\n    E(\n            Map.of(\n                    Season.SPRING , EnumSet.of( DayOfWeek.TUESDAY ) ,\n                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,\n                    Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY ) ,\n                    Season.WINTER , EnumSet.of( DayOfWeek.WEDNESDAY )\n            )\n    );\n\n    private Map &lt; Season, Set &lt; DayOfWeek &gt; &gt; map;\n\n    // Constructor\n    Group ( Map &lt; Season, Set &lt; DayOfWeek &gt; &gt; mapArg )\n    {\n        this.map = mapArg;\n    }\n\n    // Getter\n    private Map &lt; Season, Set &lt; DayOfWeek &gt; &gt; getMapOfSeasonToDaysOfWeek() {\n        return this.map ;\n    }\n\n    // Retrieve the DayOfWeek set for this particular Group.\n    public Set&lt;DayOfWeek&gt; daysForSeason (Season season ) {\n        Set&lt;DayOfWeek&gt; days =   this.map.get( season ) ; // Retrieve the value (set of days) for this key (a season) for this particular grouping of lawns/yards.\n        return days;\n    }\n\n\n\n    // Run `main` for demo/testing.\n    public static void main ( String[] args )\n    {\n        // Dump all these enum objects to console.\n        for ( Group group : EnumSet.allOf( Group.class ) )\n        {\n            System.out.println( "Group: " + group.toString() + " = " + group.getMapOfSeasonToDaysOfWeek() );\n        }\n    }\n\n}\n</code></pre>\n\n<h2><code>Schedule</code></h2>\n\n<p>Pull it all together in this <code>Schedule</code> class. </p>\n\n<p>This class makes use of the two enums defined above to get useful work done. The only method implemented so far tells you which days of the week are allowed for a particular group on a particular date. The method determines which <code>Season</code> applies for that date. </p>\n\n<p>Run the <code>main</code> method here to dump the contents of our two enums, and report on the days of the week allowing for watering in each group for a particular hard-coded date.</p>\n\n<pre><code>package com.basilbourque.watering;\n\nimport java.time.DayOfWeek;\nimport java.time.LocalDate;\nimport java.time.ZoneId;\nimport java.time.format.DateTimeFormatter;\nimport java.time.temporal.ChronoField;\nimport java.time.temporal.IsoFields;\nimport java.util.EnumSet;\nimport java.util.Set;\n\npublic class Schedule\n{\n    static private DateTimeFormatter isoWeekFormatter = DateTimeFormatter.ofPattern( "uuuu-\'W\'ww" ) ;\n\n    static public Set &lt; DayOfWeek &gt; daysForGroupOnDate ( Group group , LocalDate localDate )\n    {\n        Season season = Season.ofLocalDate( localDate );\n        Set &lt; DayOfWeek &gt; days = group.daysForSeason( season );\n        return days;\n    }\n\n    // Run `main` for demo/testing.\n    public static void main ( String[] args )\n    {\n        Season.main( null  );\n        Group.main( null  );\n        // Dump all these enum objects to console.\n        for ( Group group : EnumSet.allOf( Group.class ) )\n        {\n            LocalDate localDate = LocalDate.now( ZoneId.of( "Africa/Tunis" ) );\n            Set &lt; DayOfWeek &gt; days = Schedule.daysForGroupOnDate( group , localDate );\n            String week = localDate.format( Schedule.isoWeekFormatter  ) ; // Standard ISO 8601 week, where week number one has the first Thursday of the calendar year, and week starts on Monday, so year is either 52 or 53 weeks long.\n            String message = "Group " + group + " – Watering days on " + localDate + " week # " + week + " is: " + days;\n            System.out.println( message );\n        }\n    }\n}\n</code></pre>\n\n<h2>Console</h2>\n\n<p>When running <code>Schedule.main</code>, we see this dumped to the console.</p>\n\n<blockquote>\n  <p>Season: SPRING = [MARCH, APRIL]</p>\n  \n  <p>Season: SUMMER = [MAY, JUNE, JULY, AUGUST]</p>\n  \n  <p>Season: FALL = [SEPTEMBER, OCTOBER]</p>\n  \n  <p>Season: WINTER = [NOVEMBER, DECEMBER, JANUARY, FEBRUARY]</p>\n  \n  <p>Group: A = {SPRING=[TUESDAY, THURSDAY], FALL=[TUESDAY, THURSDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[TUESDAY]}</p>\n  \n  <p>Group: B = {SPRING=[FRIDAY], FALL=[TUESDAY, FRIDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[FRIDAY]}</p>\n  \n  <p>Group: C = {SPRING=[MONDAY], FALL=[MONDAY, TUESDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[MONDAY]}</p>\n  \n  <p>Group: D = {SPRING=[WEDNESDAY, FRIDAY], FALL=[FRIDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[WEDNESDAY]}</p>\n  \n  <p>Group: E = {SPRING=[TUESDAY], FALL=[TUESDAY, WEDNESDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[WEDNESDAY]}</p>\n  \n  <p>Group A – Watering days on 2018-01-30 week # 2018-W05 is: [TUESDAY]</p>\n  \n  <p>Group B – Watering days on 2018-01-30 week # 2018-W05 is: [FRIDAY]</p>\n  \n  <p>Group C – Watering days on 2018-01-30 week # 2018-W05 is: [MONDAY]</p>\n  \n  <p>Group D – Watering days on 2018-01-30 week # 2018-W05 is: [WEDNESDAY]</p>\n  \n  <p>Group E – Watering days on 2018-01-30 week # 2018-W05 is: [WEDNESDAY]</p>\n</blockquote>\n\n<h1>ISO 8601 week</h1>\n\n<p>You may find it helpful to learn about the <a href="https://en.wikipedia.org/wiki/ISO_8601" rel="nofollow noreferrer">ISO 8601</a> standard for a <a href="https://en.wikipedia.org/wiki/ISO_week_date" rel="nofollow noreferrer">definition of week</a>. The standard gives a specific meaning to “week” and defines a textual format for representing a particular week or a particular day within that week.</p>\n\n<p>For working with such weeks within Java, consider adding the <a href="http://www.threeten.org/threeten-extra/" rel="nofollow noreferrer"><em>ThreeTen-Extra</em></a> library to your project to make use of the <a href="http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/YearWeek.html" rel="nofollow noreferrer"><code>YearWeek</code></a> class.</p>\n\n<h1><code>LocalDate</code></h1>\n\n<p>The <a href="https://docs.oracle.com/javase/9/docs/api/java/time/LocalDate.html" rel="nofollow noreferrer"><code>LocalDate</code></a> class represents a date-only value without time-of-day and without time zone.</p>\n\n<p>A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in <a href="https://en.wikipedia.org/wiki/Europe/Paris" rel="nofollow noreferrer">Paris France</a> is a new day while still “yesterday” in <a href="https://en.wikipedia.org/wiki/America/Montreal" rel="nofollow noreferrer">Montréal Québec</a>.</p>\n\n<p>If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.</p>\n\n<p>Specify a <a href="https://en.wikipedia.org/wiki/List_of_tz_zones_by_name" rel="nofollow noreferrer">proper time zone name</a> in the format of <code>continent/region</code>, such as <a href="https://en.wikipedia.org/wiki/America/Montreal" rel="nofollow noreferrer"><code>America/Montreal</code></a>, <a href="https://en.wikipedia.org/wiki/Africa/Casablanca" rel="nofollow noreferrer"><code>Africa/Casablanca</code></a>, or <code>Pacific/Auckland</code>. Never use the 3-4 letter abbreviation such as <code>EST</code> or <code>IST</code> as they are <em>not</em> true time zones, not standardized, and not even unique(!). </p>\n\n<pre><code>ZoneId z = ZoneId.of( "America/Montreal" ) ;  \nLocalDate today = LocalDate.now( z ) ;\n</code></pre>\n\n<p>If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit.</p>\n\n<pre><code>ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.\n</code></pre>\n\n<p>Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December. </p>\n\n<pre><code>LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.\n</code></pre>\n\n<p>Or, better, use the <a href="https://docs.oracle.com/javase/9/docs/api/java/time/Month.html" rel="nofollow noreferrer"><code>Month</code></a> enum objects pre-defined, one for each month of the year. Tip: Use these <code>Month</code> objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide <a href="https://en.wikipedia.org/wiki/Type_safety" rel="nofollow noreferrer">type-safety</a>.</p>\n\n<pre><code>LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;\n</code></pre>\n\n<h1>Immutable collections</h1>\n\n<p>The lists, sets, and maps seen above should ideally be immutable collections, as changing the membership of those collections is likely to be confounding and erroneous.</p>\n\n<p>The new Java 9 syntax <code>List.of</code> and <code>Map.of</code> are already promised to be immutable. However, in our case the <code>Map</code> should ideally be an <code>EnumMap</code> for efficiency of performance and memory. The current implementation of <code>Map.of</code> and <code>Set.of</code> apparently do not detect the use of enums as members and automatically optimize with an internal use of <code>EnumMap</code> and <code>EnumSet</code>. There is a OpenJDK issue opened to consider such issues: <a href="https://bugs.openjdk.java.net/browse/JDK-8145048" rel="nofollow noreferrer"><em>consider enhancements to EnumMap and EnumSet</em></a>.</p>\n\n<p>One way to obtain an immutable EnumSet and immutable EnumMap is through the <a href="https://en.wikipedia.org/wiki/Google_Guava" rel="nofollow noreferrer">Google Guava</a> library:</p>\n\n<ul>\n<li><a href="http://google.github.io/guava/releases/snapshot-jre/api/docs/com/google/common/collect/Sets.html#immutableEnumSet-E-E...-" rel="nofollow noreferrer"><code>Sets.immutableEnumSet( … )</code></a></li>\n<li><a href="http://google.github.io/guava/releases/snapshot-jre/api/docs/com/google/common/collect/Maps.html#immutableEnumMap-java.util.Map-" rel="nofollow noreferrer"><code>Maps.immutableEnumMap( … )</code></a></li>\n</ul>\n\n<p>The results of each use an underlying <code>EnumSet</code>/<code>EnumMap</code>. Operations such as <code>get</code> and <code>put</code> throw an exception. So you get the enum-related optimizations along with immutability.</p>\n\n<p>Here are the <code>Season</code> and <code>Group</code> classes seen above modified to use the Google Guava 23.6 library.</p>\n\n<h2><code>Season</code> with immutability</h2>\n\n<pre><code>package com.basilbourque.watering;\n\nimport java.time.LocalDate;\nimport java.time.Month;\nimport java.util.EnumSet;\nimport java.util.List;\n\npublic enum Season\n{\n    SPRING( List.of( Month.MARCH , Month.APRIL ) ),  // `List.of` provides literals-style syntax, and returns an immutable `List`. New in Java 9.\n    SUMMER( List.of( Month.MAY , Month.JUNE, Month.JULY , Month.AUGUST ) ),\n    FALL( List.of( Month.SEPTEMBER , Month.OCTOBER ) ),\n    WINTER( List.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY ) );\n\n    private List&lt; Month &gt; months;\n\n    // Constructor\n    Season ( List &lt; Month &gt; monthsArg )\n    {\n        this.months = monthsArg;\n    }\n\n    public List &lt; Month &gt; getMonths ( )\n    {\n        return this.months;\n    }\n\n    // For any given month, determine the season.\n    static public Season ofLocalMonth ( Month monthArg )\n    {\n        Season s = null;\n        for ( Season season : EnumSet.allOf( Season.class ) )\n        {\n            if ( season.getMonths().contains( monthArg ) )\n            {\n                s = season;\n                break; // Bail out of this FOR loop.\n            }\n        }\n        return s;\n    }\n\n    // For any given date, determine the season.\n    static public Season ofLocalDate ( LocalDate localDateArg )\n    {\n        Month month = localDateArg.getMonth();\n        Season s = Season.ofLocalMonth( month );\n        return s;\n    }\n\n    // Run `main` for demo/testing.\n    public static void main ( String[] args )\n    {\n        // Dump all these enum objects to console.\n        for ( Season season : EnumSet.allOf( Season.class ) )\n        {\n            System.out.println( "Season: " + season.toString() + " = " + season.getMonths() );\n        }\n    }\n}\n</code></pre>\n\n<h2><code>Group</code> with immutability</h2>\n\n<pre><code>package com.basilbourque.watering;\n\nimport com.google.common.collect.Maps;\nimport com.google.common.collect.Sets;\n\nimport java.time.DayOfWeek;\nimport java.util.EnumSet;\nimport java.util.Map;\nimport java.util.Set;\n\npublic enum Group\n{\n    A(\n            Maps.immutableEnumMap(\n                    Map.of(  // `Map.of` provides literals-style syntax, and returns an immutable `Map`. New in Java 9.\n                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,\n                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,\n                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,\n                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.TUESDAY )\n                    )\n            )\n    ),\n\n    B(\n            Maps.immutableEnumMap(\n                    Map.of(\n                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.FRIDAY ) ,\n                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,\n                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.FRIDAY ) ,\n                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.FRIDAY )\n                    )\n            )\n    ),\n\n    C(\n            Maps.immutableEnumMap(\n                    Map.of(\n                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.MONDAY ) ,\n                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,\n                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.MONDAY , DayOfWeek.TUESDAY ) ,\n                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.MONDAY )\n                    )\n            )\n    ),\n\n    D(\n            Maps.immutableEnumMap(\n                    Map.of(\n                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY , DayOfWeek.FRIDAY ) ,\n                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,\n                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.FRIDAY ) ,\n                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY )\n                    )\n            )\n    ),\n\n    E(\n            Maps.immutableEnumMap(\n                    Map.of(\n                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.TUESDAY ) ,\n                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,\n                            Season.FALL , Sets.immutableEnumSet( EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY ) ) ,\n                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY )\n                    )\n            )\n    );\n\n    private Map &lt; Season, Set &lt; DayOfWeek &gt; &gt; map;\n\n    // Constructor\n    Group ( Map &lt; Season, Set &lt; DayOfWeek &gt; &gt; mapArg )\n    {\n        this.map = mapArg;\n    }\n\n    // Getter\n    private Map &lt; Season, Set &lt; DayOfWeek &gt; &gt; getMapOfSeasonToDaysOfWeek ( )\n    {\n        return this.map;\n    }\n\n    // Retrieve the DayOfWeek set for this particular Group.\n    public Set &lt; DayOfWeek &gt; daysForSeason ( Season season )\n    {\n        Set &lt; DayOfWeek &gt; days = this.map.get( season ); // Retrieve the value (set of days) for this key (a season) for this particular grouping of lawns/yards.\n        return days;\n    }\n\n    // Run `main` for demo/testing.\n    public static void main ( String[] args )\n    {\n        // Dump all these enum objects to console.\n        for ( Group group : EnumSet.allOf( Group.class ) )\n        {\n            System.out.println( "Group: " + group.toString() + " = " + group.getMapOfSeasonToDaysOfWeek() );\n        }\n    }\n\n}\n</code></pre>\n\n<hr>\n\n<h1>About java.time</h1>\n\n<p>The <a href="http://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html" rel="nofollow noreferrer">java.time</a> framework is built into Java 8 and later. These classes supplant the troublesome old <a href="https://en.wikipedia.org/wiki/Legacy_system" rel="nofollow noreferrer">legacy</a> date-time classes such as <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Date.html" rel="nofollow noreferrer"><code>java.util.Date</code></a>, <a href="https://docs.oracle.com/javase/9/docs/api/java/util/Calendar.html" rel="nofollow noreferrer"><code>Calendar</code></a>, &amp; <a href="http://docs.oracle.com/javase/9/docs/api/java/text/SimpleDateFormat.html" rel="nofollow noreferrer"><code>SimpleDateFormat</code></a>.</p>\n\n<p>The <a href="http://www.joda.org/joda-time/" rel="nofollow noreferrer">Joda-Time</a> project, now in <a href="https://en.wikipedia.org/wiki/Maintenance_mode" rel="nofollow noreferrer">maintenance mode</a>, advises migration to the <a href="http://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html" rel="nofollow noreferrer">java.time</a> classes.</p>\n\n<p>To learn more, see the <a href="http://docs.oracle.com/javase/tutorial/datetime/TOC.html" rel="nofollow noreferrer">Oracle Tutorial</a>. And search Stack Overflow for many examples and explanations. Specification is <a href="https://jcp.org/en/jsr/detail?id=310" rel="nofollow noreferrer">JSR 310</a>.</p>\n\n<p>Where to obtain the java.time classes? </p>\n\n<ul>\n<li><a href="https://en.wikipedia.org/wiki/Java_version_history#Java_SE_8" rel="nofollow noreferrer"><strong>Java SE 8</strong></a>, <a href="https://en.wikipedia.org/wiki/Java_version_history#Java_SE_9" rel="nofollow noreferrer"><strong>Java SE 9</strong></a>, and later\n\n<ul>\n<li>Built-in. </li>\n<li>Part of the standard Java API with a bundled implementation.</li>\n<li>Java 9 adds some minor features and fixes.</li>\n</ul></li>\n<li><a href="https://en.wikipedia.org/wiki/Java_version_history#Java_SE_6" rel="nofollow noreferrer"><strong>Java SE 6</strong></a> and <a href="https://en.wikipedia.org/wiki/Java_version_history#Java_SE_7" rel="nofollow noreferrer"><strong>Java SE 7</strong></a>\n\n<ul>\n<li>Much of the java.time functionality is back-ported to Java 6 &amp; 7 in <a href="http://www.threeten.org/threetenbp/" rel="nofollow noreferrer"><strong><em>ThreeTen-Backport</em></strong></a>.</li>\n</ul></li>\n<li><a href="https://en.wikipedia.org/wiki/Android_(operating_system)" rel="nofollow noreferrer"><strong>Android</strong></a>\n\n<ul>\n<li>Later versions of Android bundle implementations of the java.time classes.</li>\n<li>For earlier Android, the <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"><strong><em>ThreeTenABP</em></strong></a> project adapts <em>ThreeTen-Backport</em> (mentioned above). See <a href="http://stackoverflow.com/q/38922754/642706"><em>How to use ThreeTenABP…</em></a>.</li>\n</ul></li>\n</ul>\n\n<p>The <a href="http://www.threeten.org/threeten-extra/" rel="nofollow noreferrer"><strong>ThreeTen-Extra</strong></a> project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as <a href="http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/Interval.html" rel="nofollow noreferrer"><code>Interval</code></a>, <a href="http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/YearWeek.html" rel="nofollow noreferrer"><code>YearWeek</code></a>, <a href="http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/YearQuarter.html" rel="nofollow noreferrer"><code>YearQuarter</code></a>, and <a href="http://www.threeten.org/threeten-extra/apidocs/index.html" rel="nofollow noreferrer">more</a>.</p>\n'}]
['https://Stackoverflow.com/questions/12870', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/172/']