【问题标题】:Calculating the number of days in a month without Calendar在没有日历的情况下计算一个月中的天数
【发布时间】:2014-10-02 09:58:57
【问题描述】:

我正在尝试计算给定年份和月份数的一个月中的天数。这是我目前所拥有的。

 public static int daysInMonth(int m, int y) {
    int d;
    if (m == 1 || m == 3 || m == 5 || m == 7 
             || m == 8 || m == 10 || m == 12) { 
      d = 31;
    } else if (m == 4 || m == 6 || m == 9 || m == 11) { 
      d = 30;
    } else if (y % 4 == 0 && m == 2) {  
      d = 29;
    } else if (m == 2) {
      d = 28;   
    } else {    
      d = 0;    
    }   
    return d;   
  }

很遗憾,闰年的第二个月不能正常工作。

如何在不使用 Calendar 类的情况下修复它?

【问题讨论】:

  • 究竟哪一个失败了?
  • 那么您的问题到底是什么?如果您只是想让您的代码看起来更好或更高效地运行,您应该在codereview.stackexchange.com 上提出这个问题
  • 如果你只需要找到任何给定月份有多少天的答案,已经有一个解决方案here
  • 我在闰年第 2 个月的测试,例如(2016 年)由于某种原因未能通过测试
  • y % 4 不足以测试闰年 - 例如1900 年不是闰年

标签: java


【解决方案1】:

您需要正确计算闰年:

public static int daysInMonth(int m, int y) {
    int d;
    if (m == 1 || m == 3 || m == 5 || m == 7
             || m == 8 || m == 10 || m == 12) {
      d = 31;
    } else if (m == 4 || m == 6 || m == 9 || m == 11) {
      d = 30;
    } else if (isLeapYear(y) && m == 2) {
      d = 29;
    } else if (m == 2) {
      d = 28;
    } else {
      d = 0;
    }
    return d;
}

public static boolean isLeapYear(int year) {
  if (year % 4 != 0) {
    return false;
  } else if (year % 400 == 0) {
    return true;
  } else if (year % 100 == 0) {
    return false;
  } else {
    return true;
  }
}

here

这是一个完整且经过测试的解决方案,也带有Ideone

import java.util.HashSet;
import java.util.Arrays;
import java.util.List;

class MyClass {

  public static void main(String[] args) {
    List<Integer> leapYears = Arrays.asList(1804, 1808, 1812, 1816, 1820, 1824, 1828, 1832, 1836, 1840, 1844, 1848, 1852, 1856, 1860, 1864, 1868, 1872, 1876, 1880, 1884, 1888, 1892, 1896, 1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944, 1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2044, 2048, 2052, 2056, 2060, 2064, 2068, 2072, 2076, 2080, 2084, 2088, 2092, 2096, 2104, 2108, 2112, 2116, 2120, 2124, 2128, 2132, 2136, 2140, 2144, 2148, 2152, 2156, 2160, 2164, 2168, 2172, 2176, 2180, 2184, 2188, 2192, 2196, 2204, 2208, 2212, 2216, 2220, 2224, 2228, 2232, 2236, 2240, 2244, 2248, 2252, 2256, 2260, 2264, 2268, 2272, 2276, 2280, 2284, 2288, 2292, 2296, 2304, 2308, 2312, 2316, 2320, 2324, 2328, 2332, 2336, 2340, 2344, 2348, 2352, 2356, 2360, 2364, 2368, 2372, 2376, 2380, 2384, 2388, 2392, 2396, 2400);
    for(Integer year = 1804; year < 2400; year++) {
      for(Integer month : Arrays.asList(1,3,5,7,8,10,12)) {
        assert daysInMonth(month, year) == 31;
      }
      for(Integer month : Arrays.asList(4,6,9,11)) {
        assert daysInMonth(month, year) == 30;
      }
      if(leapYears.contains(year)) {
        assert daysInMonth(2, year) == 29;
      }
      else {
        assert daysInMonth(2, year) == 28;
      }
    }
  }

  public static int daysInMonth(int m, int y) {
    HashSet<Integer> monthsWith31Days = new HashSet<Integer>(Arrays.asList(1,3,5,7,8,10,12));
    HashSet<Integer> monthsWith30Days = new HashSet<Integer>(Arrays.asList(4,6,9,11));

    if(monthsWith31Days.contains(m)) {
      return 31;
    } else if(monthsWith30Days.contains(m)) {
      return 30;
    }
    else if(isLeapYear(y)) {
      return 29;
    }
    else {
      return 28;
    }
  }

  public static boolean isLeapYear(int year) {
    if (year % 4 != 0) {
      return false;
    } else if (year % 400 == 0) {
      return true;
    } else if (year % 100 == 0) {
      return false;
    } else {
      return true;
    }
  }
}

【讨论】:

    【解决方案2】:

    http://ideone.com/H4VAvv

    对于 2,2016 年的情况,输出结果符合预期。

    /* package whatever; // don't place package name! */
    
    import java.util.*;
    import java.lang.*;
    import java.io.*;
    
    /* Name of the class has to be "Main" only if the class is public. */
    class Ideone
    {
    public static void main (String[] args) throws java.lang.Exception
    {
        System.out.println(daysInMonth(2,2016));
    }
    public static int daysInMonth(int m, int y) {
    int d;
    if (m == 1 || m == 3 || m == 5 || m == 7 
             || m == 8 || m == 10 || m == 12) { 
      d = 31;
    } else if (m == 4 || m == 6 || m == 9 || m == 11) { 
      d = 30;
    } else if (y % 4 == 0 && m == 2) {  
      d = 29;
    } else if (m == 2) {
      d = 28;   
    } else {    
      d = 0;    
    }   
    return d;   
    }
    }
    

    【讨论】:

    • 同意,2016 年 2 月没有发现问题。您的方法按预期返回 29 天。
    【解决方案3】:

    我会将月份中的天数存储在一个整数数组中,其中第一个索引为空值以减少条件

    public static int daysInMonth(int m, int y) {
        int[] days = {0, 31, 28, 31, ... 31};
        if (m == 2 && y % 4 == 0) {
            return 29;
    
        } else {
            return days[m];
        }
    

    }

    您可能需要添加一些检查以确保 m 参数始终小于 13(月数加上开头的空值)

    【讨论】:

      【解决方案4】:

      此外,为了保持一致性,请在您的 daysInMonth 中重复使用 Date.isLeapYear,而不是硬编码 y % 4 == 0

      【讨论】:

        猜你喜欢
        • 2015-12-11
        • 2017-07-06
        • 2015-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-23
        • 1970-01-01
        相关资源
        最近更新 更多