【问题标题】:Finding every first Sunday of the month between 1900 and a user-input year查找 1900 年到用户输入年份之间的每个月的第一个星期日
【发布时间】:2014-02-20 02:03:53
【问题描述】:

这是作业。

我正在尝试查找用户输入的一年中 1900 年 1 月 1 日(我们假设是星期一)和一年中的 12 月 31 日之间的每个月的第一天发生的周日登陆。日历扩展是禁止使用的。

我以正确的格式返回日期,但它们与我们的讲师提供的示例代码不匹配。
在给定的示例中,输入 1902 应返回:
1900 年 4 月 1 日
1900 年 7 月 1 日
1901 年 9 月 1 日
1901 年 12 月 1 日
1902 年 6 月 1 日

对于 1902,我的代码返回:
1900 年 3 月 1 日
1901 年 1 月 1 日
1901 年 4 月 1 日
1901 年 5 月 1 日
1902 年 2 月 1 日
1902 年 6 月 1 日
1902 年 7 月 1 日

import java.util.Scanner;


public class Sundays {

public static void main(String[] args) {
    Scanner reader = new Scanner(System.in);

    System.out.print("Enter the ending year: ");
    int userInputYear = reader.nextInt();

    int[] orderedLengthOfMonthsArray = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    String[] orderedNamesOfMonthsArray = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
    int month = 0;
    int dayOfWeek = 1; // initialized to MONDAY Jan 1, 1900 -- Sunday would be #7
    int dayOfMonth = 1;


    for (int year = 1900; year <= userInputYear; year++) {

        for (month = 0; month < orderedLengthOfMonthsArray.length; month++) {


            for (dayOfMonth = 1; dayOfMonth <= orderedLengthOfMonthsArray[month]; dayOfMonth++) {

                dayOfWeek++;

                if (dayOfMonth == 1 && dayOfWeek == 7) {
                    System.out.println(dayOfMonth + " " + orderedNamesOfMonthsArray[month] + " " + year);
                }

                if (dayOfWeek == 8) {
                    dayOfWeek = 1;
                }                   
            }
        }
    }
}  
}

【问题讨论】:

  • 你也忽略了闰年。
  • 我应该提到我们假设没有闰年。

标签: java date


【解决方案1】:

交换if语句和dayOfWeek的增加。

        for (dayOfMonth = 1; dayOfMonth <= orderedLengthOfMonthsArray[month]; dayOfMonth++) {
            if (dayOfMonth == 1 && dayOfWeek == 7) {
                System.out.println(dayOfMonth + " " + orderedNamesOfMonthsArray[month] + " " + year);
            }

            dayOfWeek++;

            if (dayOfWeek == 8) {
                dayOfWeek = 1;
            }                   
        }

当您在 dayOfMonth for 循环中时,您已经有了正确的星期几(最初是 1900 年 1 月 1 日星期一),所以如果您先增加它,那么之后的检查将不正确。

【讨论】:

  • 有趣——这解决了它。也感谢您提供有用的解释。订单真的就是一切!
【解决方案2】:
if (dayOfWeek == 7) {
    dayOfWeek = 1;
}  

所以你的一周有 6 天?我认为您应该重置为零或在dayOfWeek 为 8 时重置。

【讨论】:

    【解决方案3】:

    有人提到Joda-Time 魔术......所以这是我使用 Joda-Time 2.3 的解决方案。

    虽然问题(家庭作业)禁止使用添加的库……

    • 这个比较可能很有启发性。
    • 学生应该很快就会知道 java.util.Date 和 Calendar 类是出了名的麻烦,在实际工作中应该避免使用。它们在 Java 8 中被新的 java.time.* package 所取代,新的 java.time.* package 受到 Joda-Time 的启发并由 JSR 310 定义。

    我的示例代码使用 LocalDate,只有在您绝对确定您不关心 (a) 时间和 (b) 时区时才应该使用它。我通常不推荐这种方法,因为那些认为自己既不需要时间也不需要区域的天真程序员往往会被证明是错误的。

    // Start
    LocalDate start = new LocalDate( 1900, 1, 1 );
    
    // Stop
    // Using "half-open" comparison. We care about December 31 of specified year, but we will test for January 1 of year after.
    String input = "1930";
    int year = Integer.valueOf( input );
    year = ( year + 1 );  // Add one to get to next year, for "half-open" approach.
    LocalDate stop = new LocalDate( year, 1, 1 );
    
    // Collect each LocalDate where the first of the month is a Sunday.
    java.util.List<LocalDate> localDates = new java.util.ArrayList<LocalDate>();
    LocalDate localDate = start;
    do {
        if ( localDate.getDayOfWeek() == DateTimeConstants.SUNDAY ) { // Comparing 'int' primitive values.
            localDates.add( localDate ); // Collect this LocalDate instance.
        }
        localDate = localDate.plusMonths( 1 ); // Move on to next month. Joda-Time is smart about various month-ends and leap-year.
    } while ( localDate.isBefore( stop ) ); // "Half-Open" means test "<" rather than "<=".
    

    转储到控制台...

    System.out.println( "The First-Of-The-Month days that are Sundays from " + start + " (inclusive) to " + stop + " (exclusive):" );
    System.out.println( localDates );
    
    The First-Of-The-Month days that are Sundays from 1900-01-01 (inclusive) to 1931-01-01 (exclusive):
    [1900-04-01, 1900-07-01, 1901-09-01, 1901-12-01, 1902-06-01, 1903-02-01, 1903-03-01, 1903-11-01, 1904-05-01, 1905-01-01, 1905-10-01, 1906-04-01, 1906-07-01, 1907-09-01, 1907-12-01, 1908-03-01, 1908-11-01, 1909-08-01, 1910-05-01, 1911-01-01, 1911-10-01, 1912-09-01, 1912-12-01, 1913-06-01, 1914-02-01, 1914-03-01, 1914-11-01, 1915-08-01, 1916-10-01, 1917-04-01, 1917-07-01, 1918-09-01, 1918-12-01, 1919-06-01, 1920-02-01, 1920-08-01, 1921-05-01, 1922-01-01, 1922-10-01, 1923-04-01, 1923-07-01, 1924-06-01, 1925-02-01, 1925-03-01, 1925-11-01, 1926-08-01, 1927-05-01, 1928-01-01, 1928-04-01, 1928-07-01, 1929-09-01, 1929-12-01, 1930-06-01]
    

    【讨论】:

    • 不错。不要忘记您可以使用localDate.toString("dd MMM yyyy"); 格式化输出,至于时区,我会使用DateMidnight 甚至DateTime + withTimeAtStartOfDay。 Joda 太酷了,你可以改变类型,它会起作用。
    • @AnthonyAccioly 有效积分,DateMidnight 除外。 Joda-Time 团队不再推荐“午夜”类和方法。在 v2.3 中添加了 withTimeAtStartOfDay 方法以取代午夜的东西。请参阅this answer by Alex 获取文档。
    【解决方案4】:

    只是为了好玩,虽然您明确提到不要使用 Calendar,但我们可以这样做:

    public static List<Date> mondaysFirst(int firstYear, int lastYear) {
        final List<Date> dates = new ArrayList<>();
        final Calendar c1 = Calendar.getInstance(Locale.US);
        c1.set(firstYear, 0, 1, 0, 0, 0);
        final Calendar c2 = Calendar.getInstance(Locale.US);
        c2.set(lastYear, 11, 31, 23, 59, 59);
    
        while (c1.before(c2)) {
            final int dayOfTheWeek = c1.get(Calendar.DAY_OF_WEEK);
            // is sunday
            if (dayOfTheWeek == 1) {
                dates.add(c1.getTime());    
            }
            c1.add(Calendar.MONTH, 1);
        }
    
        return dates;
    }
    

    并打印结果:

    final List<Date> dates = mondaysFirst(1900, 1902);
    final SimpleDateFormat sf = new SimpleDateFormat("dd MMM yyyy");
    for (Date date: dates) {
        System.out.println(sf.format(date));
    }
    

    Working Example.


    我确信有一些 Joda-Time 的魔力可以让这段时间更短。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-29
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多