Repository: briannesbitt/Carbon (php)

Issue:
isLongYear() is not determined from the ISO 8601 year
<!--
    🛑 DON'T REMOVE ME.
    This issue template applies to all
      - bug reports,
      - feature proposals,
      - and documentation requests

    Having all those informations will allow us to know exactly
    what you expect and answer you faster and precisely (answer
    that matches your Carbon version, PHP version and usage).
    
    Note: Comments between <!- - and - -> won't appear in the final
    issue (See [Preview] tab).
-->
Hello,

I encountered an issue with the following code:
<!--
    ⚠️ Your code below (not the code from inside Carbon library)
    Be sure it's dependency-free and enough to reproduce the issue
    when we run it on:
    https://play.phpsandbox.io/embed/nesbot/carbon
-->
```php
$date_1 = Carbon::parse('December 30, 2019');
$date_2 = Carbon::parse('January 1, 2020');

echo $date_1->isoFormat('G-W-E') . PHP_EOL;
echo $date_2->isoFormat('G-W-E') . PHP_EOL;

echo $date_1->isLongYear() ? 'true' : 'false' . PHP_EOL; // false, should be true if this based on the ISO year
echo $date_2->isLongYear() ? 'true' : 'false' . PHP_EOL; // true
```

Carbon version: 2.62.1
PHP version: 8.1.7

I expected to get true for both as the above dates are in ISO week 1 of 2020.  But `Carbon::parse('December 30, 2019')->isLongYear() ` is `false` while `Carbon::parse('January 1, 2020')->isLongYear()` is `true`.

<!--
    Always give your expectations. Each use has their owns.
    You may want daylight saving time to be taken into account,
    someone else want it to be ignored. You may want timezone
    to be used in comparisons, someone else may not, etc.
-->

<!--
    If you did not succeed to get the same result in
    https://play.phpsandbox.io/embed/nesbot/carbon?input=%3C%3Fphp%0A%0Aecho%20Carbon%3A%3Aparse('2018-06-01')%3B then precise the
    result you get.
-->

Thanks!

Pull request description:
Add isLongIsoYear() method
Fix #2746

Patch:
diff --git a/src/Carbon/Traits/Comparison.php b/src/Carbon/Traits/Comparison.php
index d4c2d8c8..30a4d73d 100644
--- a/src/Carbon/Traits/Comparison.php
+++ b/src/Carbon/Traits/Comparison.php
@@ -563,12 +563,17 @@ trait Comparison
     }
 
     /**
-     * Determines if the instance is a long year
+     * Determines if the instance is a long year (using calendar year).
+     *
+     * ⚠️ This method completely ignores month and day to use the numeric year number,
+     * it's not correct if the exact date matters. For instance as `2019-12-30` is already
+     * in the first week of the 2020 year, if you want to know from this date if ISO week
+     * year 2020 is a long year, use `isLongIsoYear` instead.
      *
      * @example
      * ```
-     * Carbon::parse('2015-01-01')->isLongYear(); // true
-     * Carbon::parse('2016-01-01')->isLongYear(); // false
+     * Carbon::create(2015)->isLongYear(); // true
+     * Carbon::create(2016)->isLongYear(); // false
      * ```
      *
      * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
@@ -580,6 +585,27 @@ trait Comparison
         return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53;
     }
 
+    /**
+     * Determines if the instance is a long year (using ISO 8601 year).
+     *
+     * @example
+     * ```
+     * Carbon::parse('2015-01-01')->isLongIsoYear(); // true
+     * Carbon::parse('2016-01-01')->isLongIsoYear(); // true
+     * Carbon::parse('2016-01-03')->isLongIsoYear(); // false
+     * Carbon::parse('2019-12-29')->isLongIsoYear(); // false
+     * Carbon::parse('2019-12-30')->isLongIsoYear(); // true
+     * ```
+     *
+     * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
+     *
+     * @return bool
+     */
+    public function isLongIsoYear()
+    {
+        return static::create($this->isoWeekYear, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53;
+    }
+
     /**
      * Compares the formatted values of the two dates.
      *


Test patch:
diff --git a/tests/Carbon/GettersTest.php b/tests/Carbon/GettersTest.php
index 217578e2..34a249e8 100644
--- a/tests/Carbon/GettersTest.php
+++ b/tests/Carbon/GettersTest.php
@@ -409,11 +409,28 @@ class GettersTest extends AbstractTestCase
     public function testIsLongYearTrue()
     {
         $this->assertTrue(Carbon::createFromDate(2015, 1, 1)->isLongYear());
+        $this->assertTrue(Carbon::createFromDate(2020, 1, 1)->isLongYear());
+    }
+
+    public function testIsLongIsoYearTrue()
+    {
+        $this->assertTrue(Carbon::createFromDate(2015, 1, 1)->isLongIsoYear());
+        $this->assertTrue(Carbon::createFromDate(2016, 1, 1)->isLongIsoYear());
+        $this->assertTrue(Carbon::createFromDate(2019, 12, 30)->isLongIsoYear());
     }
 
     public function testIsLongYearFalse()
     {
         $this->assertFalse(Carbon::createFromDate(2016, 1, 1)->isLongYear());
+        $this->assertFalse(Carbon::createFromDate(2019, 12, 29)->isLongYear());
+        $this->assertFalse(Carbon::createFromDate(2019, 12, 30)->isLongYear());
+    }
+
+    public function testIsLongIsoYearFalse()
+    {
+        $this->assertTrue(Carbon::createFromDate(2016, 1, 3)->isLongIsoYear());
+        $this->assertFalse(Carbon::createFromDate(2019, 12, 29)->isLongIsoYear());
+        $this->assertFalse(Carbon::createFromDate(2018, 12, 31)->isLongIsoYear());
     }
 
     public function testWeekOfMonth()
diff --git a/tests/CarbonInterval/RoundingTest.php b/tests/CarbonInterval/RoundingTest.php
index 1c8145e3..508e4970 100644
--- a/tests/CarbonInterval/RoundingTest.php
+++ b/tests/CarbonInterval/RoundingTest.php
@@ -65,6 +65,16 @@ class RoundingTest extends AbstractTestCase
         $this->assertSame(24, CarbonInterval::days(22)->roundUnit('day', 6)->totalDays);
     }
 
+    public function testTotalAfterRound()
+    {
+        var_dump(CarbonInterval::make('43h3m6s')->hours);
+        var_dump(CarbonInterval::make('43h3m6s')->cascade()->hours);
+        var_dump(CarbonInterval::make('43h3m6s')->roundMinutes()->hours);
+        exit;
+        $this->assertSame(43, CarbonInterval::make('43h3m6s')->roundMinutes()->hours);
+        $this->assertSame(43.04, CarbonInterval::make('43h3m6s')->roundMinutes()->totalHours);
+    }
+
     public function testCeil()
     {
         $this->assertSame(21, CarbonInterval::days(21)->ceilWeeks()->totalDays);