Code Duplication    Length = 66-90 lines in 2 locations

src/date/Calendar.class.php 2 locations

@@ 677-766 (lines=90) @@
674
                $this->pinField(DateDefinitions::DAY_OF_MONTH);
675
                return;
676
677
            case DateDefinitions::WEEK_OF_MONTH:
678
                {
679
                        // This is tricky, because during the roll we may have to shift
680
                        // to a different day of the week.  For example:
681
682
                        //    s  m  t  w  r  f  s
683
                        //          1  2  3  4  5
684
                        //    6  7  8  9 10 11 12
685
686
                        // When rolling from the 6th or 7th back one week, we go to the
687
                        // 1st (assuming that the first partial week counts).  The same
688
                        // thing happens at the end of the month.
689
690
                        // The other tricky thing is that we have to figure out whether
691
                        // the first partial week actually counts or not, based on the
692
                        // minimal first days in the week.  And we have to use the
693
                        // correct first day of the week to delineate the week
694
                        // boundaries.
695
696
                        // Here's our algorithm.  First, we find the real boundaries of
697
                        // the month.  Then we discard the first partial week if it
698
                        // doesn't count in this locale.  Then we fill in the ends with
699
                        // phantom days, so that the first partial week and the last
700
                        // partial week are full weeks.  We then have a nice square
701
                        // block of weeks.  We do the usual rolling within this block,
702
                        // as is done elsewhere in this method.  If we wind up on one of
703
                        // the phantom days that we added, we recognize this and pin to
704
                        // the first or the last day of the month.  Easy, eh?
705
706
                        // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
707
                        // in this locale.  We have dow in 0..6.
708
                        $dow = $this->internalGet(DateDefinitions::DAY_OF_WEEK) - $this->getFirstDayOfWeek();
709
                if ($dow < 0) {
710
                    $dow += 7;
711
                }
712
713
                        // Find the day of the week (normalized for locale) for the first
714
                        // of the month.
715
                        $fdm = ($dow - $this->internalGet(DateDefinitions::DAY_OF_MONTH) + 1) % 7;
716
                if ($fdm < 0) {
717
                    $fdm += 7;
718
                }
719
720
                        // Get the first day of the first full week of the month,
721
                        // including phantom days, if any.  Figure out if the first week
722
                        // counts or not; if it counts, then fill in phantom days.  If
723
                        // not, advance to the first real full week (skip the partial week).
724
                if ((7 - $fdm) < $this->getMinimalDaysInFirstWeek()) {
725
                    $start = 8 - $fdm; // Skip the first partial week
726
                } else {
727
                    $start = 1 - $fdm; // This may be zero or negative
728
                }
729
730
                        // Get the day of the week (normalized for locale) for the last
731
                        // day of the month.
732
                        $monthLen = $this->getActualMaximum(DateDefinitions::DAY_OF_MONTH);
733
                        $ldm = ($monthLen - $this->internalGet(DateDefinitions::DAY_OF_MONTH) + $dow) % 7;
734
                        // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here.
735
736
                        // Get the limit day for the blocked-off rectangular month; that
737
                        // is, the day which is one past the last day of the month,
738
                        // after the month has already been filled in with phantom days
739
                        // to fill out the last week.  This day has a normalized DOW of 0.
740
                        $limit = $monthLen + 7 - $ldm;
741
742
                        // Now roll between start and (limit - 1).
743
                        $gap = $limit - $start;
744
                        $day_of_month = ($this->internalGet(DateDefinitions::DAY_OF_MONTH) + $amount * 7 - $start) % $gap;
745
                if ($day_of_month < 0) {
746
                    $day_of_month += $gap;
747
                }
748
                        $day_of_month += $start;
749
750
                        // Finally, pin to the real start and end of the month.
751
                if ($day_of_month < 1) {
752
                    $day_of_month = 1;
753
                }
754
                if ($day_of_month > $monthLen) {
755
                    $day_of_month = $monthLen;
756
                }
757
758
                        // Set the DAY_OF_MONTH.  We rely on the fact that this field
759
                        // takes precedence over everything else (since all other fields
760
                        // are also set at this point).  If this fact changes (if the
761
                        // disambiguation algorithm changes) then we will have to unset
762
                        // the appropriate fields here so that DAY_OF_MONTH is attended
763
                        // to.
764
                        $this->set(DateDefinitions::DAY_OF_MONTH, $day_of_month);
765
                return;
766
            }
767
            case DateDefinitions::WEEK_OF_YEAR:
768
                {
769
                    // This follows the outline of WEEK_OF_MONTH, except it applies
@@ 767-832 (lines=66) @@
764
                        $this->set(DateDefinitions::DAY_OF_MONTH, $day_of_month);
765
                return;
766
            }
767
            case DateDefinitions::WEEK_OF_YEAR:
768
                {
769
                    // This follows the outline of WEEK_OF_MONTH, except it applies
770
                    // to the whole year.  Please see the comment for WEEK_OF_MONTH
771
                    // for general notes.
772
773
                    // Normalize the DAY_OF_WEEK so that 0 is the first day of the week
774
                    // in this locale.  We have dow in 0..6.
775
                    $dow = $this->internalGet(DateDefinitions::DAY_OF_WEEK) - $this->getFirstDayOfWeek();
776
                if ($dow < 0) {
777
                    $dow += 7;
778
                }
779
780
                    // Find the day of the week (normalized for locale) for the first
781
                    // of the year.
782
                    $fdy = ($dow - $this->internalGet(DateDefinitions::DAY_OF_YEAR) + 1) % 7;
783
                if ($fdy < 0) {
784
                    $fdy += 7;
785
                }
786
787
                    // Get the first day of the first full week of the year,
788
                    // including phantom days, if any.  Figure out if the first week
789
                    // counts or not; if it counts, then fill in phantom days.  If
790
                    // not, advance to the first real full week (skip the partial week).
791
                if ((7 - $fdy) < $this->getMinimalDaysInFirstWeek()) {
792
                    $start = 8 - $fdy; // Skip the first partial week
793
                } else {
794
                    $start = 1 - $fdy; // This may be zero or negative
795
                }
796
797
                    // Get the day of the week (normalized for locale) for the last
798
                    // day of the year.
799
                    $yearLen = $this->getActualMaximum(DateDefinitions::DAY_OF_YEAR);
800
                    $ldy = ($yearLen - $this->internalGet(DateDefinitions::DAY_OF_YEAR) + $dow) % 7;
801
                    // We know yearLen >= DAY_OF_YEAR so we skip the += 7 step here.
802
803
                    // Get the limit day for the blocked-off rectangular year; that
804
                    // is, the day which is one past the last day of the year,
805
                    // after the year has already been filled in with phantom days
806
                    // to fill out the last week.  This day has a normalized DOW of 0.
807
                    $limit = $yearLen + 7 - $ldy;
808
809
                    // Now roll between start and (limit - 1).
810
                    $gap = $limit - $start;
811
                    $day_of_year = ($this->internalGet(DateDefinitions::DAY_OF_YEAR) + $amount * 7 - $start) % $gap;
812
                if ($day_of_year < 0) {
813
                    $day_of_year += $gap;
814
                }
815
                    $day_of_year += $start;
816
817
                    // Finally, pin to the real start and end of the month.
818
                if ($day_of_year < 1) {
819
                    $day_of_year = 1;
820
                }
821
                if ($day_of_year > $yearLen) {
822
                    $day_of_year = $yearLen;
823
                }
824
825
                    // Make sure that the year and day of year are attended to by
826
                    // clearing other fields which would normally take precedence.
827
                    // If the disambiguation algorithm is changed, this section will
828
                    // have to be updated as well.
829
                    $this->set(DateDefinitions::DAY_OF_YEAR, $day_of_year);
830
                    $this->clear(DateDefinitions::MONTH);
831
                return;
832
            }
833
            case DateDefinitions::DAY_OF_YEAR:
834
                {
835
                    // Roll the day of year using millis.  Compute the millis for