代码之家  ›  专栏  ›  技术社区  ›  Bruce the Hoon

使用JAVA从日期识别季节

  •  1
  • Bruce the Hoon  · 技术社区  · 18 年前

    从那以后我除了好运什么都没有了,为什么不再试一次呢?

    我有一个应用程序需要根据一年中的季节(春天、夏天、冬天、秋天)显示不同的图像。这些季节我有非常具体的开始和结束日期。

    我想从你们这些天才那里得到的是一个名为getSeason的方法,它将日期作为输入,并返回一个字符串值:春、夏、冬或秋。以下是日期范围及其相关季节:

    春季:3/1-4/30
    夏季:5/1-8/31
    秋季:9 / 1-10 / 31
    冬季:11/1-2/28

    有人能提供一种工作方法来返回合适的季节吗? 谢谢大家!

    9 回复  |  直到 7 年前
        1
  •  6
  •   Vlad Holubiev    10 年前

    似乎只要检查一下月份就可以了:

    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.
    
        2
  •  3
  •   Basil Bourque    10 年前

    这里有一些很好的答案,但它们已经过时了。java.time类使这项工作更加容易。

    Java.时间

    与最早版本的Java捆绑在一起的麻烦的旧类已经被 java.time 构建到Java 8和以后的类。见 Oracle Tutorial . 许多功能已经被移植到Java 6和7中。 ThreeTen-Backport 并进一步适应安卓 ThreeTenABP .

    Month

    考虑到这里用整个月来定义季节,我们可以利用 Month enum . 这样的枚举值比仅仅的整数值(1-12)要好,因为它们是类型安全的,并且可以保证有效值。

    EnumSet

    安 EnumSet 是跟踪枚举值子集的一种快速、紧凑的内存方法。

    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 );
    

    例如,我们得到特定时区的当前时刻。

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

    询问日期时间值 月份 .

    Month month = Month.from( zdt );
    

    寻找哪个季节 枚举集 通过调用 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.
    }
    

    定义您自己的__Season__Enum

    如果您在代码库中使用这个季节概念,我建议您定义自己的枚举,即__season_。

    基本枚举很简单: public enum Season { SPRING, SUMMER, FALL, WINTER; } . 但是我们也添加了一个静态方法 of 查找哪个月对应哪个季节。

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

    下面是如何使用该枚举。

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

    转储到控制台。

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

    ZDT:2016-06-25T18:23:14.695-04:00[美国/蒙特利尔]月:6月季:夏季

        3
  •  1
  •   helloandre    18 年前

    我觉得受人恩惠,但受宠若惊。所以我来做。

    这不仅检查月份,而且检查每月的某一天。

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

    我相信这很可怕,可以改进。在评论中告诉我。

        4
  •  1
  •   nsayer    18 年前

    嗯,它可以像

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

    在评论中,我被指责为一个更好的解决方案:枚举:

    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");
        }
    }
    
        5
  •  1
  •   Jérôme Verstrynge    15 年前
    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");
    
    
     }
    
    }
    
        6
  •  1
  •   ECE    12 年前

    尝试使用哈希表或枚举。您可以将日期转换为某个值(1月1日为1,…),然后为某个字段创建容器。或者可以对月份进行枚举。一月:冬天,二月:冬天,…七月:夏天,等等

        7
  •  0
  •   Jorn    18 年前

    因为在这个范围内,所有季节都是完整的月份,所以您可以切换到日期的月份:

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

    我建议使用所有12个日历常量来完成整个切换,而不是最后一个日历常量的默认值。然后可以确保输入正确,例如

    default:
     throw new IllegalArgumentException();
    

    最后。

    根据您的用例,您可能还希望在季节中使用枚举,而不是简单的字符串。

    注意Debug .GETMUNTH()方法,你应该使用java. UTI.Calase.GET(日历。月)来代替。(只需使用calendar.setdate(yourdate)将日期转换为日历)

        8
  •  0
  •   Volodymyr Machekhin    10 年前

    简单解

     Calendar calendar = Calendar.getInstance();
     calendar.setTimeInMillis(timeInMills);
     int month = calendar.get(Calendar.MONTH);
     CurrentSeason = month == 11 ? 0 : (month + 1) / 3;
    
        9
  •  0
  •   Meno Hochschild    7 年前

    您问题的标题非常笼统,因此大多数用户会首先想到天文季节。尽管您问题的详细内容仅限于自定义的日期范围,但这一限制可能是由于无法计算天文情况造成的,因此我敢对这个旧问题发表答案,也适用于天文情况。

    这里的大多数答案都是基于完整的月份。我在这里举两个例子来说明天文季节和基于任意日期范围的季节。

    a)任意日期范围到季节的映射

    在这里 我们肯定需要额外的信息,具体的时区 或者抵消,否则我们不能翻译一个瞬间(就像老式的 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);
    

    我使用了一个简单的helper枚举 public enum Season { SPRING, SUMMER, FALL, WINTER; } .

    b)天文季节

    这里我们还需要一个额外的信息,即如果季节是在北半球或南半球。我的图书馆 Time4J 基于预定义的枚举提供以下解决方案 AstronomicalSeason 使用版本v5.2:

        // 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);