morilog / jalali

This Package helps developers to easily work with Jalali (Shamsi or Iranian) dates in php appliations, based on Jalali (Shamsi) DateTime class.
MIT License
861 stars 110 forks source link

Wrong result in subMonths() #51

Closed smhnaqvi closed 6 years ago

smhnaqvi commented 6 years ago

Hello dear,
Algorithm of thesubMonths() function has a problem for subtracting months which results a date in previous year.
I propose you a simple implementation as follow:

    public function subMonths(int $months = 1): Jalalian
    {
        Assertion::greaterOrEqualThan($months, 1);

        $years = (int)($months / 12);
        $newDate = clone $this;
        if($years > 0)
            $newDate  = $this->subYears($years);

        $rem = $months % 12;
        $targetMonth = $newDate->getMonth() - $rem;
        if($targetMonth > 0) {
            $day = $newDate->getDay();
            $targetMonthDays = $newDate->getDaysOf($targetMonth);
            $targetDay = $day <= $targetMonthDays ? $day : $targetMonthDays;
            return new static(
                $newDate->getYear(),
                $targetMonth,
                $targetDay,
                $newDate->getHour(),
                $newDate->getMinute(),
                $newDate->getSecond(),
                $newDate->getTimezone()
            );
        } else {
            $targetMonth = 12 - abs($targetMonth);
            $day = $newDate->getDay();
            $targetMonthDays = $newDate->getDaysOf($targetMonth);
            $targetDay = $day <= $targetMonthDays ? $day : $targetMonthDays;
            return new static(
                $newDate->getYear() - 1,
                $targetMonth,
                $targetDay,
                $newDate->getHour(),
                $newDate->getMinute(),
                $newDate->getSecond(),
                $newDate->getTimezone()
            );
        }
   }
morilog commented 6 years ago

what kind of problems? please give me some examples.

Hesammousavi commented 6 years ago

lets take an example : i wrote this code jdate(); // output : 1397-08-02 11:00:00 but when i wrote this code - you can see result in bottom jdate()->subMonths(1); // output : 1398-02-03 11:00:00 i think that it doesn't work correctly

morilog commented 6 years ago

I wrote a test in local with this lines:

       $jDate = Jalalian::fromFormat('Y-m-d H:i:s', '1397-08-02 11:00:00');
       $this->assertEquals('1397-07-02', $jDate->subMonths()->format('Y-m-d'));

and it was passed!

maybe you installed old version of this package and get wrong results

Hesammousavi commented 6 years ago

yeah , you're right i figure out that why i got it because of beberlei/assert's version i had beberlei/assert dev-master so composer installed morilog/jalali version 3.0.7 so i removed it and then i reinstalled morilog/jalali it installed last version of morilog (3.0.12) and now i don't have this issues , tnx