Чистый код. Создание, анализ и рефакторинг — страница 72 из 94

 == 0) {

511             return false;

512         }

513         else {

514             return true;

515         }

516

517     }

518

519     /**

520      * Возвращает количество високосных годов от 1900 до заданного года

521      * ВКЛЮЧИТЕЛЬНО.

522      * 

523      * Учтите, что 1900 год високосным не является.

524      *

525      * @param yyyy  год (в диапазоне от 1900 до 9999).

526      *

527      * @return количество високосных годов от 1900 до заданного года.

528      */

529     public static int leapYearCount(final int yyyy) {

530

531         final int leap4 = (yyyy - 1896) / 4;

532         final int leap100 = (yyyy - 1800) / 100;

533         final int leap400 = (yyyy - 1600) / 400;

534         return leap4 - leap100 + leap400;

535

536     }

537

538     /**

539      * Возвращает номер последнего дня месяца с учетом

540      * високосных годов.

541      *

542      * @param month  месяц.

543      * @param yyyy  год (в диапазоне от 1900 до 9999).

544      *

545      * @return номер последнего дня месяца.

546      */

547     public static int lastDayOfMonth(final int month, final int yyyy) {

548

549         final int result = LAST_DAY_OF_MONTH[month];

550         if (month != FEBRUARY) {

551             return result;

552         }

553         else if (isLeapYear(yyyy)) {

554             return result + 1;

555         }

556         else {

557             return result;

558         }

559

560     }

561

562     /**

563      * Создает новую дату, прибавляя заданное количество дней

564      *  к базовой дате.

565      *

566      * @param days  количество прибавляемых дней (может быть отрицательным).

567      * @param base  базовая дата.

568      *

569      * @return новая дата.

570      */

571     public static SerialDate addDays(final int days, final SerialDate base) {

572

573         final int serialDayNumber = base.toSerial() + days;

574         return SerialDate.createInstance(serialDayNumber);

575

576     }

577

578     /**

579      * Создает новую дату, прибавляя заданное количество месяцев

580      * к базовой дате.

581      * 

582      * Если базовая дата близка к концу месяца, результат может слегка

583      * смещаться:  31 мая + 1 месяц = 30 июня

584      *

585      * @param months  количество прибавляемых месяцев (может быть отрицательным).

586      * @param base  базовая дата.

587      *


Листинг Б.1 (продолжение)

588      * @return новая дата.

589      */

590     public static SerialDate addMonths(final int months,

591                                        final SerialDate base) {

592

593         final int yy = (12 * base.getYYYY() + base.getMonth() + months - 1)

594                        / 12;

595         final int mm = (12 * base.getYYYY() + base.getMonth() + months - 1)

596                        % 12 + 1;

597         final int dd = Math.min(

598             base.getDayOfMonth(), SerialDate.lastDayOfMonth(mm, yy)

599         );

600         return SerialDate.createInstance(dd, mm, yy);

601

602     }

603

604     /**

605      * Создает новую дату, прибавляя заданное количество лет

606      * к базовой дате.

607      *

608      * @param years  количество прибавляемых лет (может быть отрицательным).

609      * @param base  базовая дата.

610      *

611      * @return новая дата.

612      */

613     public static SerialDate addYears(final int years, final SerialDate base) {

614

615         final int baseY = base.getYYYY();

616         final int baseM = base.getMonth();

617         final int baseD = base.getDayOfMonth();

618

619         final int targetY = baseY + years;

620         final int targetD = Math.min(

621             baseD, SerialDate.lastDayOfMonth(baseM, targetY)

622         );

623

624         return SerialDate.createInstance(targetD, baseM, targetY);

625

626     }

627

628     /**

629      * Возвращает последнюю дату, приходящуюся на заданный день недели,

630      * ПРЕДШЕСТВУЮЩУЮ базовой дате.

631      *

632      * @param targetWeekday  код дня недели.

633      * @param base  базовая дата.

634      *

635      * @return последняя дата, приходящаяся на заданный день недели,

636      *         ПРЕДШЕСТВУЮЩАЯ базовой дате.

637      */

638     public static SerialDate getPreviousDayOfWeek(final int targetWeekday,

639                                                   final SerialDate base) {

640

641         // Проверить аргументы...

642         if (!SerialDate.isValidWeekdayCode(targetWeekday)) {

643             throw new IllegalArgumentException(

644                 "Invalid day-of-the-week code."