0

例: 日付範囲は 2013 年 1 月 3 日から 2013 年 10 月 3 日です。上記の範囲では、3 か月ごとの最初の週のすべての平日を取得します。結果は次のようになります。

Thu Jan 03 00:00:00 ICT 2013
Fri Jan 04 00:00:00 ICT 2013
Sat Jan 05 00:00:00 ICT 2013
Sun Jan 06 00:00:00 ICT 2013
Mon Jan 07 00:00:00 ICT 2013
Mon Apr 01 00:00:00 ICT 2013
Tue Apr 02 00:00:00 ICT 2013
Wed Apr 03 00:00:00 ICT 2013
Thu Apr 04 00:00:00 ICT 2013
Fri Apr 05 00:00:00 ICT 2013
Sat Apr 06 00:00:00 ICT 2013
Sun Apr 07 00:00:00 ICT 2013
Mon Jul 01 00:00:00 ICT 2013
Tue Jul 02 00:00:00 ICT 2013
Wed Jul 03 00:00:00 ICT 2013
Thu Jul 04 00:00:00 ICT 2013
Fri Jul 05 00:00:00 ICT 2013
Sat Jul 06 00:00:00 ICT 2013
Sun Jul 07 00:00:00 ICT 2013
Tue Oct 01 00:00:00 ICT 2013
Wed Oct 02 00:00:00 ICT 2013

私はそれを行う方法を考え出しましたが、コードはかなり醜く見えるので、もっとエレガントな方法があるのだろうか? 助けてくれてありがとう、本当に感謝しています。

// set up the startCal and endCal
String fmtShowTime = "ddMMyy"; // TODO: move to configurations
SimpleDateFormat sdf = new SimpleDateFormat(fmtShowTime);
TimeZone defaultZone = TimeZone.getDefault();
sdf.setTimeZone(defaultZone);
String fromTime = "030113";
String toTime = "031013";
Date startDate = sdf.parse(fromTime);
Date endDate = sdf.parse(toTime);
Calendar startCal = Calendar.getInstance();
startCal.setTime(startDate);
Calendar endCal = Calendar.getInstance();
endCal.setTime(endDate);

// set up the condition for week and month
Integer week = Integer.parseInt("1"); // first week
Integer monthPeriod = Integer.parseInt("3"); // every 3 months
Integer counter = 0;

while (startCal.getTimeInMillis() < endCal.getTimeInMillis()) {
    if (startCal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == week) {
        // check if the current day in loop is the day of first week in month
        if (monthPeriod == 1)  {
            // get for every month
            for (int i = 0; i < 7; i++) {
                    if (startCal.get(Calendar.DAY_OF_WEEK_IN_MONTH) != week || startCal.getTimeInMillis() == endCal.getTimeInMillis()) {
                        // break for case like Tuesday, January 8th (2nd Tuesday of January) or October 4th (range breached) 
                        break;
                    }
                    System.out.println(startCal.getTime());
                    // move 1 more day
                    startCal.add(Calendar.DAY_OF_MONTH, 1);
            }
        }
        else {
            counter++;
            if (counter % monthPeriod == 1) {
                // I used counter mod monthPeriod to check if 3 months has passed in the loop, 1%3 = 1, 4%3 = 1 and so on
                for (int i = 0; i < 7; i++) {
                    if (startCal.get(Calendar.DAY_OF_WEEK_IN_MONTH) != week || startCal.getTimeInMillis() == endCal.getTimeInMillis()) {
                        // break for case like Tuesday, January 8th (2nd Tuesday of January) or October 4th (range breached)  
                        break;
                    }
                    System.out.println(startCal.getTime());
                    // move 1 more day
                    startCal.add(Calendar.DAY_OF_MONTH, 1);
                }
            } else {
                //if it's the first week of a month but not 3 months has passed yet then I forward 7 days to pass the check for first week of the month
                startCal.add(Calendar.DAY_OF_MONTH, 7);
            }
        }
    }
    startCal.add(Calendar.DAY_OF_MONTH, 1);
}

PSコードがあなたの目を傷つけた場合は申し訳ありませんが、それが悪いことはわかっています:)

4

2 に答える 2

0

週末を含めるか含めないかは少し不明です。ただし、要件に対する私の最善の推測に基づいて機能すると思われるものは次のとおりです。

public class DateIntervalDayParser {

    // Test harness
    public static void main(final String[] args) throws Exception {
        final int monthInterval = 3;
        final int daysFromStartOfMonth = 7;

        final DateIntervalDayParser parser = new DateIntervalDayParser();
        final List<Date> allWeekdays = parser.getWeekdays(
                new GregorianCalendar(2013, 0, 15), new GregorianCalendar(2013, 9, 15), monthInterval, daysFromStartOfMonth);

        for (final Date weekday : allWeekdays) {
            System.out.println(weekday);
        }
    }

    private List<Date> getWeekdays(final Calendar start, final Calendar end, final int monthInterval, int daysFromStartOfMonth)
    {
        // Start result list
        final List<Date> allWeekdays = new ArrayList<Date>();

        adjustStart(start, daysFromStartOfMonth);

        // Continue until start time has passed end time
        while (isMonthBeforeOrEqual(start, end)) {
            addWeekdays(allWeekdays, start, daysFromStartOfMonth);

            // Add month interval
            // NOTE: always set day of month to 1st day of month after 1st month
            start.set(Calendar.DAY_OF_MONTH, 1);
            start.add(Calendar.MONTH, monthInterval);

            // If we are in the last month, set last day of month maximum to last
            // months day if it is less than a week from the start of the month
            if (start.get(Calendar.YEAR) == end.get(Calendar.YEAR)
                    && start.get(Calendar.MONTH) == end.get(Calendar.MONTH)
                    && end.get(Calendar.DAY_OF_MONTH) < daysFromStartOfMonth) {
                daysFromStartOfMonth = end.get(Calendar.DAY_OF_MONTH);
            }
        }

        return allWeekdays;
    }

    private void adjustStart(final Calendar start, int daysFromStartOfMonth) {
        // If day of month in 1st month has passed max days from start of month,
        // start from the start of the next month
        if (start.get(Calendar.DAY_OF_MONTH) > daysFromStartOfMonth) {
            start.set(Calendar.DAY_OF_MONTH, 1);
            start.add(Calendar.MONTH, 1);
        }
    }

    private boolean isMonthBeforeOrEqual(final Calendar start, final Calendar end) {
        boolean beforeOrEqual = false;
        final int startYear = start.get(Calendar.YEAR);
        final int endYear = end.get(Calendar.YEAR);
        if (startYear < endYear) {
            beforeOrEqual = true;
        } else if (startYear == endYear) {
            beforeOrEqual = start.get(Calendar.MONTH) <= end.get(Calendar.MONTH);
        }
        return beforeOrEqual;
    }

    private void addWeekdays(final List<Date> days, final Calendar calendar, final int daysFromStartOfMonth) {
        // Add dates until day of month is exceeded
        int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        while (dayOfMonth <= daysFromStartOfMonth) {
            days.add(calendar.getTime());

            // Increment
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            dayOfMonth++;
        }
    }
}

一般的な注意事項。ロジックを管理しやすい小さなメソッドに分割することをお勧めします。そのようなコードを簡単に再利用できるようになるだけでなく、複雑さが軽減されて保守が容易になります。

于 2013-01-15T12:32:04.883 に答える
0

私の解決策を見る

    GregorianCalendar c1 = new GregorianCalendar(2013, 0, 3);
    GregorianCalendar c2 = new GregorianCalendar(2013, 9, 3);
    while (c1.before(c2)) {
        if (c1.get(Calendar.WEEK_OF_MONTH) == 1 && c1.get(Calendar.MONTH) % 3 == 0) {
            System.out.println(c1.getTime());
        }
        c1.add(Calendar.DAY_OF_MONTH, 1);
    }
于 2013-01-15T12:07:09.363 に答える