使用 Java 从日期中识别季节
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/189468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Identifying the season from the Date using Java
提问by Bruce the Hoon
I've had nothing but good luck from SO, so why not try again?
我从 SO 那里得到了好运,所以为什么不再试一次呢?
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:
我想从你们这些天才那里得到一个名为 GetSeason 的方法,它以日期作为输入并返回 Spring、Summer、Winter 或 Fall 的 String 值。以下是日期范围及其相关的季节:
Spring:3/1-4/30
Summer:5/1-8/31
Fall:9/1-10/31
Winter: 11/1-2/28
春季:3/1-4/30
夏季:5/1-8/31
秋季:9/1-10/31
冬季:11/1-2/28
Can someone provide a working method to return the proper season? Thanks everyone!
有人可以提供一种工作方法来返回适当的季节吗?感谢大家!
回答by billjamesdev
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.
回答by Basil Bourque
Some good answers here, but they are outdated. The java.time classes make this work much easier.
这里有一些很好的答案,但它们已经过时了。java.time 类使这项工作更容易。
java.time
时间
The troublesome old classes bundled with the earliest versions of Java have been supplanted by the java.timeclasses built into Java 8 and later. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backportand further adapted to Android in ThreeTenABP.
与最早版本的 Java 捆绑在一起的麻烦的旧类已被Java 8 及更高版本中内置的java.time类所取代。请参阅Oracle 教程。许多功能已被后移植到Java 6和7在ThreeTen-反向移植和在进一步适于到Android ThreeTenABP。
Month
Month
Given that seasons are defined here using whole months, we can make use of the handy Monthenum. Such enum values are better than mere integer values (1-12) because they are type-safe and you are guaranteed of valid values.
鉴于这里使用整月定义季节,我们可以使用方便的enum。这样的枚举值比单纯的整数值 (1-12) 更好,因为它们是类型安全的,并且可以保证有效值。Month
EnumSet
EnumSet
An EnumSetis a fast-performing and compact-memory way to track a subset of enum values.
AnEnumSet是一种跟踪枚举值子集的快速性能和紧凑型内存方式。
EnumSet<Month> spring = EnumSet.of( Month.MARCH , Month.APRIL );
EnumSet<Month> summer = EnumSet.of( Month.MAY , Month.JUNE , Month.JULY , Month.AUGUST );
EnumSet<Month> fall = EnumSet.of( Month.SEPTEMBER , Month.OCTOBER );
EnumSet<Month> winter = EnumSet.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY );
As an example, we get the current moment for a particular time zone.
例如,我们获取特定时区的当前时刻。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( zoneId );
Ask that date-time value for its Month.
询问该日期时间值的Month.
Month month = Month.from( zdt );
Look for which season EnumSethas that particular Month value by calling contains.
EnumSet通过调用查找哪个季节具有特定的 Month 值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.
}
Define your own “Season” enum
定义您自己的“季节”枚举
If you are using this season idea around your code base, I suggest defining your own enum, “Season”.
如果你在你的代码库中使用这个季节的想法,我建议定义你自己的枚举,“Season”。
The basic enum is simple: public enum Season { SPRING, SUMMER, FALL, WINTER; }. But we also add a static method ofto do that lookup of which month maps to which season.
基本的枚举很简单:public enum Season { SPRING, SUMMER, FALL, WINTER; }. 但是我们还添加了一个静态方法of来查找哪个月份映射到哪个季节。
package work.basil.example;
import java.time.Month;
public enum Season {
SPRING, SUMMER, FALL, WINTER;
static public Season of ( final 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;
}
}
}
Or use the switch expressions feature (JEP 361) of Java 14.
或者使用Java 14的 switch 表达式功能 ( JEP 361)。
package work.basil.example;
import java.time.Month;
import java.util.Objects;
public enum Season
{
SPRING, SUMMER, FALL, WINTER;
static public Season of ( final Month month )
{
Objects.requireNonNull( month , "ERROR - Received null where a `Month` is expected. Message # 0ac03df9-1c5a-4c2d-a22d-14c40e25c58b." );
return
switch ( Objects.requireNonNull( month ) )
{
// Spring.
case MARCH , APRIL -> Season.SPRING;
// Summer.
case MAY , JUNE , JULY , AUGUST -> Season.SUMMER;
// Fall.
case SEPTEMBER , OCTOBER -> Season.FALL;
// Winter.
case NOVEMBER , DECEMBER , JANUARY , FEBRUARY -> Season.WINTER;
}
;
}
}
Here is how to use that enum.
这是如何使用该枚举。
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now ( zoneId );
Month month = Month.from ( zdt );
Season season = Season.of ( month );
Dump to console.
转储到控制台。
System.out.println ( "zdt: " + zdt + " | month: " + month + " | season: " + season );
zdt: 2016-06-25T18:23:14.695-04:00[America/Montreal] | month: JUNE | season: SUMMER
zdt: 2016-06-25T18:23:14.695-04:00[美国/蒙特利尔] | 月份:六月 | 季节:夏季
回答by nsayer
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");
}
}
回答by helloandre
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.
我敢肯定这很可怕,并且可以改进。请在评论中告诉我。
回答by Hjohnson
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) {
System.out.println("The season is Spring");
} else if ((month == 6) && (day <= 20)) {
System.out.println("The season is Spring");
} else if (month == 6) {
System.out.println("The season is Summer");
} else if ((month == 9) && (day <= 20)) {
System.out.println("The season is Summer");
} else if (month == 9) {
System.out.println("The season is Autumn");
} else if ((month == 12) && (day <= 21)) {
System.out.println("The season is Autumn");
} else if (month == 12) {
System.out.println("The season is Winter");
}
}
}
回答by ECE
Try using hash tables or enums. You could convert the date into some value (jan 1 being 1,...) and then create bins for a certain field. or you could do an enum with the month. {january: winter, february: winter, ...july:summer, etc}
尝试使用哈希表或枚举。您可以将日期转换为某个值(jan 1 为 1,...),然后为某个字段创建 bin。或者您可以对月份进行枚举。{一月:冬天,二月:冬天,...七月:夏天,等等}
回答by Volodymyr Machekhin
Simple solution
简单的解决方案
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeInMills);
int month = calendar.get(Calendar.MONTH);
CurrentSeason = month == 11 ? 0 : (month + 1) / 3;
回答by Meno Hochschild
The title of your question is very general so most users will first think of astronomical seasons. Even though the detailed content of your question is limited to customized date ranges, this limitation might just be caused by the inability to calculate the astronomical case so I dare to post an answer to this old question also for the astronomical scenario.
你的问题的标题很笼统,所以大多数用户首先会想到天文季节。尽管您问题的详细内容仅限于自定义日期范围,但这种限制可能只是由于无法计算天文案例造成的,因此我敢于将这个老问题的答案也用于天文场景。
And most answers here are only based on full months. I give here two examples to address both astronomical seasons and seasons based on arbitrary date ranges.
这里的大多数答案仅基于整月。我在这里给出了两个例子来解决基于任意日期范围的天文季节和季节问题。
a) mapping of arbitrary date ranges to seasons
a) 任意日期范围到季节的映射
Here we definitely need an extra information, the concrete time zoneor offset otherwise we cannot translate an instant (like the oldfashioned java.util.Date-instance of your input) to a local representation using the combination of month and day. For simplicity I assume the system time zone.
在这里,我们肯定需要额外的信息,具体的时区或偏移量,否则我们无法java.util.Date使用月和日的组合将瞬间(如您输入的老式 -实例)转换为本地表示。为简单起见,我假设系统时区。
// your input
java.util.Date d = new java.util.Date();
ZoneId tz = ZoneId.systemDefault();
// extract the relevant month-day
ZonedDateTime zdt = d.toInstant().atZone(tz);
MonthDay md = MonthDay.of(zdt.getMonth(), zdt.getDayOfMonth());
// a definition with day-of-month other than first is possible here
MonthDay beginOfSpring = MonthDay.of(3, 1);
MonthDay beginOfSummer = MonthDay.of(5, 1);
MonthDay beginOfAutumn = MonthDay.of(9, 1);
MonthDay beginOfWinter = MonthDay.of(11, 1);
// determine the season
Season result;
if (md.isBefore(beginOfSpring)) {
result = Season.WINTER;
} else if (md.isBefore(beginOfSummer)) {
result = Season.SPRING;
} else if (md.isBefore(beginOfAutumn)) {
result = Season.SUMMER;
} else if (md.isBefore(beginOfWinter)) {
result = Season.FALL;
} else {
result = Season.WINTER;
}
System.out.println(result);
I have used a simple helper enum like public enum Season { SPRING, SUMMER, FALL, WINTER; }.
我使用了一个简单的辅助枚举,如public enum Season { SPRING, SUMMER, FALL, WINTER; }.
b) astronomical seasons
b) 天文季节
Here we also need one extra information, namely if the season is on the northern or on the southern hemisphere. My library Time4Joffers following solution based on the predefined enum AstronomicalSeasonusing the version v5.2:
这里我们还需要一个额外的信息,即季节是在北半球还是在南半球。我的库Time4J基于使用 v5.2 版本的预定义枚举AstronomicalSeason提供以下解决方案:
// your input
java.util.Date d = new java.util.Date();
boolean isSouthern = false;
Moment m = TemporalType.JAVA_UTIL_DATE.translate(d);
AstronomicalSeason result = AstronomicalSeason.of(m);
if (isSouthern) { // switch to southern equivalent if necessary
result = result.onSouthernHemisphere();
}
System.out.println(result);
回答by Vadzim
In case just a season number for northern hemisphere is needed:
如果只需要北半球的季节编号:
/**
* @return 1 - winter, 2 - spring, 3 - summer, 4 - autumn
*/
private static int getDateSeason(LocalDate date) {
return date.plus(1, MONTHS).get(IsoFields.QUARTER_OF_YEAR);
}
Via How do I discover the Quarter of a given Date?.
通过如何发现给定日期的季度?.
And here is how to calculate season bounds for a given date:
以下是计算给定日期的季节界限的方法:
private static LocalDate atStartOfSeason(LocalDate date) {
return date.plus(1, MONTHS).with(IsoFields.DAY_OF_QUARTER, 1).minus(1, MONTHS);
}
private static LocalDate afterEndOfSeason(LocalDate date) {
return atStartOfSeason(date).plus(3, MONTHS);
}
Via How to get the first date and last date of current quarter in java.util.Date.
回答by Jorn
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
我建议使用所有 12 个日历常量完成整个切换,而不是最后一个的默认值。然后您可以确保您的输入是正确的,例如
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.
根据您的用例,您可能还想为季节使用 Enum,而不是简单的字符串。
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))
请注意 Date.getMonth() 方法已被弃用,您应该使用 java.util.Calendar.get(Calendar.MONTH) 代替。(只需使用 calendar.setDate(yourDate) 将日期转换为日历)

