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

645             );

646         }

647

648         // Определить дату...

649         final int adjust;

650         final int baseDOW = base.getDayOfWeek();

651         if (baseDOW > targetWeekday) {

652             adjust = Math.min(0, targetWeekday - baseDOW);

653         }

654         else {

655             adjust = -7 + Math.max(0, targetWeekday - baseDOW);

656         }

657

658         return SerialDate.addDays(adjust, base);

659

660     }

661

662     /**

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

664      * ПОСЛЕ базовой даты.

665      *

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

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

668      *

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

670      *         ПОСЛЕ базовой даты.

671      */

672     public static SerialDate getFollowingDayOfWeek(final int targetWeekday,

673                                                    final SerialDate base) {

674

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

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

677             throw new IllegalArgumentException(

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

679             );

680         }

681

682         // Определить дату...

683         final int adjust;

684         final int baseDOW = base.getDayOfWeek();

685         if (baseDOW > targetWeekday) {

686             adjust = 7 + Math.min(0, targetWeekday - baseDOW);

687         }

688         else {


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

689             adjust = Math.max(0, targetWeekday - baseDOW);

690         }

691

692         return SerialDate.addDays(adjust, base);

693     }

694

695     /**

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

697      * САМУЮ БЛИЗКУЮ к базовой дате.

698      *

699      * @param targetDOW  код дня недели.

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

701      *

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

703      *         САМАЯ БЛИЗКАЯ к базовой дате.

704      */

705     public static SerialDate getNearestDayOfWeek(final int targetDOW,

706                                                  final SerialDate base) {

707

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

709         if (!SerialDate.isValidWeekdayCode(targetDOW)) {

710             throw new IllegalArgumentException(

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

712             );

713         }

714

715         // Определить дату...

716         final int baseDOW = base.getDayOfWeek();

717         int adjust = -Math.abs(targetDOW - baseDOW);

718         if (adjust >= 4) {

719             adjust = 7 - adjust;

720         }

721         if (adjust <= -4) {

722             adjust = 7 + adjust;

723         }

724         return SerialDate.addDays(adjust, base);

725

726     }

727

728     /**

729      * Перемещает дату к последнему дню месяца.

730      *

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

732      *

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

734      */

735     public SerialDate getEndOfCurrentMonth(final SerialDate base) {

736         final int last = SerialDate.lastDayOfMonth(

737             base.getMonth(), base.getYYYY()

738         );

739         return SerialDate.createInstance(last, base.getMonth(), base.getYYYY());

740     }

741

742     /**

743      * Возвращает строку, соответствующую коду недели в месяце.

744      * 

745      * Необходимо поискать более элегантное решение.

746      *

747      * @param count  целочисленный код недели в месяце.

748      *

749      * @return строка, соответствующая коду недели в месяце.

750      */

751     public static String weekInMonthToString(final int count) {

752

753         switch (count) {

754             case SerialDate.FIRST_WEEK_IN_MONTH : return "First";

755             case SerialDate.SECOND_WEEK_IN_MONTH : return "Second";

756             case SerialDate.THIRD_WEEK_IN_MONTH : return "Third";

757             case SerialDate.FOURTH_WEEK_IN_MONTH : return "Fourth";

758             case SerialDate.LAST_WEEK_IN_MONTH : return "Last";

759             default :

760                 return "SerialDate.weekInMonthToString(): invalid code.";

761         }

762

763     }

764

765     /**

766      * Возвращает строку, представляющую переданное значение relative.

767      * 

768      * Необходимо поискать более элегантное решение.

769      *

770      * @param relative  константа, представляющая значение’relative’.

771      *

772      * @return строка, представляющая переданное значение ‘relative’.

773      */

774     public static String relativeToString(final int relative) {

775

776         switch (relative) {