tags:

views:

655

answers:

4

I've had nothing but good luck from SO, so why not try again?

I have an application that needs to show a different image based on the season of the year (spring, summer, winter, fall). I have very specific start and end dates for these seasons.

What I would like from you geniuses is a method called GetSeason that takes a date as input and returns a String value of Spring, Summer, Winter or Fall. Here are the date ranges and their associated seasons:

Spring:3/1-4/30
Summer:5/1-8/31
Fall:9/1-10/31
Winter: 11/1-2/28

Can someone provide a working method to return the proper season? Thanks everyone!

+1  A: 

Well, it could be as simple as

String getSeason(int month) {
    switch(month) {
          case 11:
          case 12:
          case 1:
          case 2:
                return "winter";
          case 3:
          case 4:
                return "spring";
          case 5:
          case 6:
          case 7:
          case 8:
                return "summer";
          default:
                return "autumn";
      }
}

I have been chided in the comments into a better solution: enums:

public static Enum Season {
    WINTER(Arrays.asList(11,12,1,2)),
    SPRING(Arrays.asList(3,4)),
    SUMMER(Arrays.asList(5,6,7,8)),
    AUTUMN(Arrays.asList(9,10));

    Season(List<Integer> months) {
        this.monthlist = months;
    }
    private List<Integer> monthlist;
    public boolean inSeason(int month) {
        return this.monthlist.contains(month);  // if months are 0 based, then insert +1 before the )
    }

    public static Season seasonForMonth(int month) {
        for(Season s: Season.values()) {
            if (s.inSeason(month))
                 return s;
        }
        throw new IllegalArgumentException("Unknown month");
    }
}
nsayer
Not my favorite, as I hate using default for actual known responses, and multiple returns are bad form, but it's serviceable.
Bill James
Well, the sophisticated answer is to use an enum. I will edit.
nsayer
month = numeric value-1 so jan = 0, feb = 1.. dec = 11.at leat, according to Calendar.* constants.
Andreas Petersson
Ya, Andreas is right... you had it right before, oddly. Also, were you actually trying to make this slower? :) Anyway, it's kind of a silly question overall, but wow, did you go off the deep end here.
Bill James
Wait, just saw Contagious' answer. You are forgiven. This answer isn't NEARLY as childish as that one.
Bill James
Well, I'm tired of editing this answer. This system has the benefit of having the list of months for a season comma separated on the same line of code as the name of the season. That makes it more maintainable than a switch.
nsayer
A: 

since in this range all seasons are full months, you can do a switch with the month from your date:

switch (date.getMonth()) {
    case Calendar.JANUARY:
    case Calendar.FEBRUARY:
         return "winter";
    case Calendar.MARCH:
         return "spring";
    //etc
}

I recommend completing the entire switch using all 12 Calendar constants, instead of default for the last ones. You can then make sure your input was correct, for example with

default:
 throw new IllegalArgumentException();

at the end.

You might also want to use an Enum for the season, instead of a simple string, depending on your use cases.

Note the Date.getMonth() method is deprecated, you should use java.util.Calendar.get(Calendar.MONTH) instead. (just convert the Date to a Calendar using calendar.setDate(yourDate))

Jorn
+2  A: 

Seems like just checking the month would do:

private static final String seasons[] = {
  "Winter", "Winter", "Spring", "Spring", "Summer", "Summer", 
  "Summer", "Summer", "Fall", "Fall", "Winter", "Winter"
};
public String getSeason( Date date ) {
   return seasons[ date.getMonth() ];
}

// As stated above, getMonth() is deprecated, but if you start with a Date, 
// you'd have to convert to Calendar before continuing with new Java, 
// and that's not fast.
Bill James
Not doin' any homework here. My college days are far behind me. Check my profile for my other Java question to see the use case.
Bruce the Hoon
k, got rid of the reference. Most people don't read these, but didn't mean offense.
Bill James
+1  A: 

i feel patronized, but flattered. so i'll do it.

This checks not only the month, but day of month.

import java.util.*

public String getSeason(Date today, int year){

    // the months are one less because GC is 0-based for the months, but not days.
    // i.e. 0 = January.
    String returnMe = "";

    GregorianCalender dateToday = new GregorianCalender(year, today.get(Calender.MONTH_OF_YEAR), today.get(Calender.DAY_OF_MONTH);
    GregorianCalender springstart = new GregorianCalender(year, 2, 1);
    GregorianCalender springend = new GregorianCalender(year, 3, 30);
    GregorianCalender summerstart = new GregorianCalender(year, 4, 1);
    GregorianCalender summerend = new GregorianCalender(year, 7, 31);
    GregorianCalender fallstart = new GregorianCalender(year, 8, 1);
    GregorianCalender fallend = new GregorianCalender(year, 9, 31);
    GregorianCalender winterstart = new GregorianCalender(year, 10, 1);
    GregorianCalender winterend = new GregorianCalender(year, 1, 28);

    if ((dateToday.after(springstart) && dateToday.before(springend)) || dateToday.equals(springstart) || dateToday.equals(springend)){
        returnMe = "Spring";

    else if ((dateToday.after(summerstart) && dateToday.before(summerend)) || dateToday.equals(summerstart) || dateToday.equals(summerend)){
        returnMe = "Summer";

    else if ((dateToday.after(fallstart) && dateToday.before(fallend)) || dateToday.equals(fallstart) || dateToday.equals(fallend)){
        returnMe = "Fall";

    else if ((dateToday.after(winterstart) && dateToday.before(winterend)) || dateToday.equals(winterstart) || dateToday.equals(winterend)){
        returnMe = "Winter";

    else {
        returnMe = "Invalid";
    }
    return returnMe;
}

I'm sure this is hideous, and can be improved. let me know in the comments.

contagious
Ok, good comments first: You handle the day of Month thing well, so if he decides to take 2 days from Fall to give to Summer, you've got the easiest fix. Plus, you use Calendar correctly.
Bill James
Now for the bad: You create 8 Calendar objects EVERY TIME the function is called, when only 4 are necessary (figure it out), and they can be created once and re-used. Also, why return "Invalid"? Throw an exception if somehow today's date isn't in one of the 4 seasons, k?
Bill James
I'm curious as to why the current year isn't somehow stored in the Date argument. Seems like it would be.
Bill James