Identificare la stagione dalla data usando Java

Non ho avuto nulla ma buona fortuna da SO, quindi perché non provare di nuovo?

Ho un’applicazione che deve mostrare un’immagine diversa in base alla stagione dell’anno (spring, estate, inverno, autunno). Ho delle date di inizio e fine molto specifiche per queste stagioni.

Quello che vorrei da voi geni è un metodo chiamato GetSeason che prende una data come input e restituisce un valore String di Spring, Summer, Winter o Fall. Ecco gli intervalli di date e le stagioni associate:

Molla: 3 / 1-4 / 30
Estate: 5 / 1-8 / 31
Autunno: 9 / 1-10 / 31
Inverno: 11 / 1-2 / 28

Qualcuno può fornire un metodo di lavoro per restituire la stagione giusta? Grazie a tutti!

Sembra proprio che controllare il mese possa fare:

private static final String seasons[] = { "Winter", "Winter", "Spring", "Spring", "Spring", "Summer", "Summer", "Summer", "Fall", "Fall", "Fall", "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. 

Alcune buone risposte qui, ma sono obsolete. Le classi java.time rendono questo lavoro molto più semplice.

java.time

Le fastidiose vecchie classi in bundle con le prime versioni di Java sono state soppiantate dalle classi java.time incorporate in Java 8 e versioni successive. Vedi Oracle Tutorial . Gran parte delle funzionalità è stata sottoposta a backup su Java 6 e 7 in ThreeTen-Backport e ulteriormente adattata ad Android in ThreeTenABP .

Month

Dato che le stagioni sono definite qui utilizzando interi mesi, possiamo fare uso del pratico Month enum . Tali valori di enumerazione sono migliori dei semplici valori interi (1-12) perché sono sicuri per i tipi e sono garantiti valori validi.

EnumSet

Un EnumSet è un modo di esecuzione veloce e memoria compatta per tracciare un sottoinsieme di valori enum.

 EnumSet spring = EnumSet.of( Month.MARCH , Month.APRIL ); EnumSet summer = EnumSet.of( Month.MAY , Month.JUNE , Month.JULY , Month.AUGUST ); EnumSet fall = EnumSet.of( Month.SEPTEMBER , Month.OCTOBER ); EnumSet winter = EnumSet.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY ); 

Ad esempio, otteniamo il momento attuale per un determinato fuso orario.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.now( zoneId ); 

Chiedi il valore data-ora per il suo Month .

 Month month = Month.from( zdt ); 

Cerca per quale stagione EnumSet ha quel particolare valore del mese chiamando contains .

 if ( spring.contains( month ) ) { … } else if ( summer.contains( month ) ) { … } else if ( fall.contains( month ) ) { … } else if ( winter.contains( month ) ) { … } else { // FIXME: Handle reaching impossible point as error condition. } 

Definisci il tuo enum di “Stagione”

Se stai usando questa idea di stagione attorno al tuo codice base, ti suggerisco di definire il tuo enum, “Season”.

L’enum di base è semplice: public enum Season { SPRING, SUMMER, FALL, WINTER; } public enum Season { SPRING, SUMMER, FALL, WINTER; } . Ma aggiungiamo anche un metodo statico per fare quella ricerca di quali mappe del mese a quale stagione.

 package com.example.javatimestuff; import java.time.Month; public enum Season { SPRING, SUMMER, FALL, WINTER; static public Season of ( Month month ) { switch ( month ) { // Spring. case MARCH: // Java quirk: An enum switch case label must be the unqualified name of an enum. So cannot use `Month.MARCH` here, only `MARCH`. return Season.SPRING; case APRIL: return Season.SPRING; // Summer. case MAY: return Season.SUMMER; case JUNE: return Season.SUMMER; case JULY: return Season.SUMMER; case AUGUST: return Season.SUMMER; // Fall. case SEPTEMBER: return Season.FALL; case OCTOBER: return Season.FALL; // Winter. case NOVEMBER: return Season.WINTER; case DECEMBER: return Season.WINTER; case JANUARY: return Season.WINTER; case FEBRUARY: return Season.WINTER; default: System.out.println ( "ERROR." ); // FIXME: Handle reaching impossible point as error condition. return null; } } } 

Ecco come usare quell’enumerazione.

 ZoneId zoneId = ZoneId.of ( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.now ( zoneId ); Month month = Month.from ( zdt ); Season season = Season.of ( month ); 

Scarica alla console.

 System.out.println ( "zdt: " + zdt + " | month: " + month + " | season: " + season ); 

zdt: 2016-06-25T18: 23: 14.695-04: 00 [America / Montreal] | mese: GIUGNO | stagione: ESTATE

Mi sento patronato, ma lusingato. quindi lo farò.

Questo controlla non solo il mese, ma il giorno del mese.

 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. // ie 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; } 

Sono sicuro che è orribile e può essere migliorato. Fatemi sapere nei commenti.

Beh, potrebbe essere semplice come

 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"; } } 

Sono stato rimproverato nei commenti in una soluzione migliore: enum:

 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 months) { this.monthlist = months; } private List 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"); } } 
 import java.util.Scanner; public class lab6project1 { public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); System.out.println("This program reports the season for a given day and month"); System.out.println("Please enter the month and day as integers with a space between the month and day"); int month = keyboard.nextInt(); int day = keyboard.nextInt(); if ( (month == 1) || (month == 2)) System.out.println("The season is Winter"); else if ( (month == 4) || (month == 5)) System.out.println("The season is Spring"); else if ( (month == 7) || (month == 8)) System.out.println("The season is Summer"); else if ( (month == 10)|| (month == 11)) System.out.println("The season is Fall"); else if ( (month == 3) && (day <= 19 )) System.out.println("The season is Winter"); else if ( (month == 3) && (day >= 20 )) System.out.println("The season is Spring"); else if ( (month == 6) && (day <= 20 )) System.out.println("The season is Spring"); else if ( (month == 6) && (day >= 21 )) System.out.println("The season is Summer"); else if ( (month == 9) && (day <= 20 )) System.out.println("The season is Summer"); else if ( (month == 9) && (day >= 21 )) System.out.println("The season is Autumn"); else if ( (month == 12) && (day <= 21 )) System.out.println("The season is Autumn"); else if ( (month == 12) && (day >= 22 )) System.out.println("The season is Winter"); } } 

Prova a utilizzare le tabelle hash o le enumerazioni. È ansible convertire la data in un valore (jan 1 è 1, …) e quindi creare bin per un determinato campo. oppure potresti fare un enum con il mese. {gennaio: inverno, febbraio: inverno, … luglio: estate, ecc.}

poiché in questo intervallo tutte le stagioni sono mesi interi, puoi effettuare un passaggio con il mese dalla tua data:

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

Raccomando di completare l’intero switch utilizzando tutte le 12 costanti del calendario, anziché l’impostazione predefinita per le ultime. Puoi quindi assicurarti che il tuo input sia corretto, ad esempio con

 default: throw new IllegalArgumentException(); 

alla fine.

Potresti anche voler usare un Enum per la stagione, invece di una semplice stringa, a seconda dei casi d’uso.

Nota che il metodo Date.getMonth () è deprecato, dovresti usare java.util.Calendar.get (Calendar.MONTH). (basta convertire la data in un calendario usando calendar.setDate (yourDate))

Soluzione semplice

  Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(timeInMills); int month = calendar.get(Calendar.MONTH); CurrentSeason = month == 11 ? 0 : (month + 1) / 3;