【问题标题】:Calculating for leap year [duplicate]计算闰年[重复]
【发布时间】:2012-10-12 20:58:42
【问题描述】:

我在 Eclipse 中使用 Java 编写了这个程序。
我能够使用我在注释掉部分中解释的公式。
使用 for 循环,我可以遍历一年中的每个月,我对此代码感觉很好,对我来说它看起来干净流畅。也许我可以给变量全名以使所有内容更具可读性,但我只是在其基本本质中使用公式:)

我的问题是它不能正确计算像 2008 年这样的年份...闰年。
我知道 如果 (年 % 400 == 0 || (年 % 4 == 0 && 年 % 100 != 0)) 那么我们有一个闰年。

如果这一年是闰年,我可能需要从某个月份中减去一定天数。

任何解决方案或某些方向都非常感谢:)

package exercises;

public class E28 {
/*
 * Display the first days of each month
 * Enter the year
 * Enter first day of the year
 * 
 * h = (q + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5j) % 7
 * 
 * h is the day of the week (0: Saturday, 1: Sunday ......)
 * q is the day of the month
 * m is the month (3: March 4: April.... January and Feburary are 13 and 14)
 * j is the century (year / 100)
 * k is the year of the century (year %100)
 * 
 */
public static void main(String[] args) {
    java.util.Scanner input = new java.util.Scanner(System.in);
    System.out.print("Enter the year: ");
    int year = input.nextInt();

    int j = year / 100; // Find century for formula
    int k = year % 100; // Find year of century for formula

    // Loop iterates 12 times. Guess why.
    for (int i = 1, m = i; i <= 12; i++) { // Make m = i. So loop processes formula once for each month
        if (m == 1 || m == 2)              
            m += 12;                       // Formula requires that Jan and Feb are represented as 13 and 14
        else
            m = i;                         // if not jan or feb, then set m to i

        int h = (1 + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5 * j) % 7; // Formula created by a really smart man somewhere
        // I let the control variable i steer the direction of the formual's m value

        String day;
        if (h == 0)
            day = "Saturday";
        else if (h == 1)
            day = "Sunday";
        else if (h == 2)
            day = "Monday";
        else if (h == 3)
            day = "Tuesday";
        else if (h == 4)
            day = "Wednesday";
        else if (h == 5)
            day = "Thursday";
        else 
            day = "Friday";

        switch (m) {
        case 13: 
            System.out.println("January 1, " + year + " is " + day);
            break;
        case 14:
            System.out.println("Feburary 1, " + year + " is " + day);
            break;
        case 3:
            System.out.println("March 1, " + year + " is " + day);
            break;
        case 4:
            System.out.println("April 1, " + year + " is " + day);
            break;
        case 5:
            System.out.println("May 1, " + year + " is " + day);
            break;
        case 6:
            System.out.println("June 1, " + year + " is " + day);
            break;
        case 7:
            System.out.println("July 1, " + year + " is " + day);
            break;
        case 8:
            System.out.println("August 1, " + year + " is " + day);
            break;
        case 9:
            System.out.println("September 1, " + year + " is " + day);
            break;
        case 10:
            System.out.println("October 1, " + year + " is " + day);
            break;
        case 11:
            System.out.println("November 1, " + year + " is " + day);
            break;
        case 12:
            System.out.println("December 1, " + year + " is " + day);
            break;
        }
    }
}
}

【问题讨论】:

  • 这个问题属于 StackOverflow,而不是这里。

标签: java


【解决方案1】:

您需要开发自己的算法吗? GregorianCalendar 类有方法:

boolean isLeapYear(int year)

如果 year 是闰年,此方法返回 true,否则返回 false。

【讨论】:

  • OP 的问题不在于确定哪一年是闰年,而是如何计算这一年是闰年时的星期几。
【解决方案2】:

您应该使用JodaTime 来处理Java 中与日期有关的所有事情,而且它很容易使用。

使用 JodaTime,您不必担心闰年或其他任何事情,因为它会为您处理一切。一个简单的 for 循环和一个 DateTime 对象将满足您的需求。

    int year = 2012;

    DateTime dt = new DateTime(year, 01, 01, 00, 00, 00, 00);
    for (int i = 0; i < 12; i++) {
        System.out.println(dt.toString() + " " + dt.property(DateTimeFieldType.dayOfWeek()).getAsText());
        dt = dt.plusMonths(1);
    }

您显然会用您的输入替换 year 变量,但基本上代码是这样工作的:

  • 为从 1 月 1 日开始的年份输入初始化一个 DateTime 对象。
  • 以文本格式打印出当前的 DateTime 和星期几
  • 将 DateTime 对象中的月份增加 1。

输出:

2012-01-01T00:00:00.000+11:00 Sunday
2012-02-01T00:00:00.000+11:00 Wednesday
2012-03-01T00:00:00.000+11:00 Thursday
. . . 

【讨论】:

  • 不会称尤达“易于使用”...
  • 谢谢,我更喜欢这个主意。
  • 我正在介绍 Java 编程的偶数练习作为自学。感谢您的帮助。
  • 我会搞砸的。我想格式化这个的输出。并且定义参数令人困惑?
  • 您可以在 DateTime 对象上获得一堆不同的输出,请查看 API 文档。我当时只是为了方便而使用了 toString()。
【解决方案3】:

int h = (1 + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5 * j) % 7; // 某个地方的一个非常聪明的人创建的公式

这是你的问题。该公式是以克里斯蒂安·泽勒(Christian Zeller)命名的Zeller's Congruence。你没有正确使用它。问题在于,在此公式中,您必须将 1 月和 2 月视为上一年的第 13th 和 14th 个月。例如,您需要将 2000 年 2 月作为 1999 年的第 14 个月。

附录
您的程序会产生 2000 年 2 月 1 日的星期四。正确答案是星期二。

例如,让我们使用公式计算 2000 年 2 月 29 日的星期几。(该算法是通用的;只需将您的 1 替换为月份中的日期。)

现在是 2 月,所以我们必须按照 1999 年的第 14 个月来计算。这样,j 是 19,k 是 99,m 是 14。我将使用 @ 987654325@ 而不是1 在同余。有了这个,h = (d + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5*j) % 7 = (29 + (26*(14+1))/10 + 99 + 99/4 + 19/4 + 5*19) % 7 = 290 % 7 = 3。从星期六=0 算起,就是星期二。

为了验证,一个快速而肮脏的 perl 脚本:

#!/usr/bin/perl
# Usage: dayofweek.pl <year number> <month number> <day of month>
# Validation of inputs is an exercise left to the reader.
my ($y, $m, $d) = @ARGV;
use integer; 
my $wd = [qw(Sun Mon Tues Wednes Thurs Fri Satur)]->
         [(index `cal $m $y | tail +3 | grep -E "(^| )$d( |\$)"`, $d) / 3]; 
print "$y/$m/$d -> ${wd}day\n";

2000 2 29 运行此程序会产生2000/2/29 -&gt; Tuesday,正如预期的那样。

【讨论】:

  • 谢谢,上一年忘记调整了。
【解决方案4】:

我没有查看您的代码,但是对于闰年检查,您应该这样做:(来源:Wiki-Leap Year Alg.

if year modulo 400 is 0 then
   is_leap_year
else if year modulo 100 is 0 then
   not_leap_year
else if year modulo 4 is 0 then
   is_leap_year
else
   not_leap_year

还可以在此处查看类似的问题(和答案): stackOverFlow-calc-leap-year

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 2016-01-01
相关资源
最近更新 更多