Repository: briannesbitt/Carbon (PHP)

Issue:
⭐ Add floatDiffInWeeks() method
<!--
    🛑 DON'T REMOVE ME.
    This issue template apply 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:
```php
echo Carbon::now()->floatDiffInWeeks(new Carbon("Last day of December this year"));
```

Carbon version: **2.32.0**

PHP version: **7.2**

<!--
    Run the command `composer show nesbot/carbon`
    to get "versions"
    Use `echo phpversion();`
    to get PHP version.

    Some issues can depends on your context, settings,
    macros, timezone, language. So to be sure the code
    you give is enough to reproduce your bug, try it
    first in:
    https://try-carbon.herokuapp.com/?theme=xcode&export&embed

    You can use the [Options] button to change the version
    then when you get the bug with this editor, you can use
    the [Export] button, copy the link of the opened tab,
    then paste it in the issue. Then we can immediatly get
    your issue.
-->


I expected to get:

```
17.43
```
<!--
    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.
-->

But I actually get:

```bash

   BadMethodCallException  : Method floatDiffInWeeks does not exist.

  at /{PROJECT_DIR}/vendor/nesbot/carbon/src/Carbon/Traits/Date.php:2588
    2584|                     }
    2585|                 }
    2586| 
    2587|                 if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
  > 2588|                     throw new BadMethodCallException("Method $method does not exist.");
    2589|                 }
    2590| 
    2591|                 return null;
    2592|             }

  Exception trace:

  1   Carbon\Carbon::Carbon\Traits\{closure}()
      /{PROJECT_DIR}/vendor/nesbot/carbon/src/Carbon/Traits/Mixin.php:153

  2   Carbon\Carbon::bindMacroContext(Object(Carbon\Carbon), Object(Closure))
      /{PROJECT_DIR}/vendor/nesbot/carbon/src/Carbon/Traits/Date.php:2595

  Please use the argument -v to see more details.
```
<!--
    If you did not succeed to get the same result in
    https://try-carbon.herokuapp.com/ then precise the
    result you get.
-->

Thanks!



Discussion:
Hello,

All the `floatDiffIn*` methods are listed in examples in the documentation. The absence of a method is not a bug, this is a feature request.

As this sounds not like a big deal to add (considering it would return the diff in days / days per week), I would agree to implement this feature.

This is open to pull-requests.

Thanks.
As a work-around you also can use a macro for this:
```php
Carbon::macro('floatDiffInWeeks', function (...$params) {
  return self::this()->floatDiffInDays(...$params) / Carbon::DAYS_PER_WEEK;
});

echo Carbon::now()->floatDiffInWeeks(new Carbon("Last day of December this year"));
```
It will be available in 2.40.0 release.



Patch:
diff --git a/src/Carbon/CarbonInterface.php b/src/Carbon/CarbonInterface.php
index b4de568aa3..0444de1cb4 100644
--- a/src/Carbon/CarbonInterface.php
+++ b/src/Carbon/CarbonInterface.php
@@ -897,6 +897,23 @@ public function betweenIncluded($date1, $date2): bool;
      */
     public function calendar($referenceTime = null, array $formats = []);
 
+    /**
+     * Checks if the (date)time string is in a given format and valid to create a
+     * new instance.
+     *
+     * @example
+     * ```
+     * Carbon::canBeCreatedFromFormat('11:12:45', 'h:i:s'); // true
+     * Carbon::canBeCreatedFromFormat('13:12:45', 'h:i:s'); // false
+     * ```
+     *
+     * @param string $date
+     * @param string $format
+     *
+     * @return bool
+     */
+    public static function canBeCreatedFromFormat($date, $format);
+
     /**
      * Return the Carbon instance passed through, a now instance in the same timezone
      * if null given or parse the input if string given.
@@ -1810,6 +1827,16 @@ public function floatDiffInRealMonths($date = null, $absolute = true);
      */
     public function floatDiffInRealSeconds($date = null, $absolute = true);
 
+    /**
+     * Get the difference in weeks as float (microsecond-precision).
+     *
+     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+     * @param bool                                                   $absolute Get the absolute of the difference
+     *
+     * @return float
+     */
+    public function floatDiffInRealWeeks($date = null, $absolute = true);
+
     /**
      * Get the difference in year as float (microsecond-precision) using timestamps.
      *
@@ -1830,6 +1857,16 @@ public function floatDiffInRealYears($date = null, $absolute = true);
      */
     public function floatDiffInSeconds($date = null, $absolute = true);
 
+    /**
+     * Get the difference in weeks as float (microsecond-precision).
+     *
+     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+     * @param bool                                                   $absolute Get the absolute of the difference
+     *
+     * @return float
+     */
+    public function floatDiffInWeeks($date = null, $absolute = true);
+
     /**
      * Get the difference in year as float (microsecond-precision).
      *
@@ -2346,8 +2383,6 @@ public function gte($date): bool;
      * Carbon::hasFormat('13:12:45', 'h:i:s'); // false
      * ```
      *
-     * @SuppressWarnings(PHPMD.EmptyCatchBlock)
-     *
      * @param string $date
      * @param string $format
      *
diff --git a/src/Carbon/Factory.php b/src/Carbon/Factory.php
index 1029ffeb0c..854c552437 100644
--- a/src/Carbon/Factory.php
+++ b/src/Carbon/Factory.php
@@ -17,6 +17,8 @@
  *
  * <autodoc generated by `composer phpdoc`>
  *
+ * @method bool                                               canBeCreatedFromFormat($date, $format)                                                                                             Checks if the (date)time string is in a given format and valid to create a
+ *                                                                                                                                                                                               new instance.
  * @method Carbon|false                                       create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null)                                           Create a new Carbon instance from a specific date and time.
  *                                                                                                                                                                                               If any of $year, $month or $day are set to null their now() values will
  *                                                                                                                                                                                               be used.
diff --git a/src/Carbon/FactoryImmutable.php b/src/Carbon/FactoryImmutable.php
index 8775c4c5b9..dbc43f9ad2 100644
--- a/src/Carbon/FactoryImmutable.php
+++ b/src/Carbon/FactoryImmutable.php
@@ -17,6 +17,8 @@
  *
  * <autodoc generated by `composer phpdoc`>
  *
+ * @method bool                                               canBeCreatedFromFormat($date, $format)                                                                                             Checks if the (date)time string is in a given format and valid to create a
+ *                                                                                                                                                                                               new instance.
  * @method CarbonImmutable|false                              create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $tz = null)                                           Create a new Carbon instance from a specific date and time.
  *                                                                                                                                                                                               If any of $year, $month or $day are set to null their now() values will
  *                                                                                                                                                                                               be used.
diff --git a/src/Carbon/Traits/Difference.php b/src/Carbon/Traits/Difference.php
index a3db605141..61fee45b06 100644
--- a/src/Carbon/Traits/Difference.php
+++ b/src/Carbon/Traits/Difference.php
@@ -26,7 +26,6 @@
  * Depends on the following methods:
  *
  * @method bool lessThan($date)
- * @method DateInterval diff(\DateTimeInterface $date, bool $absolute = false)
  * @method static copy()
  * @method static resolveCarbon($date = null)
  * @method static Translator translator()
@@ -500,6 +499,19 @@ public function floatDiffInDays($date = null, $absolute = true)
         return ($hoursDiff < 0 ? -1 : 1) * $this->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
     }
 
+    /**
+     * Get the difference in weeks as float (microsecond-precision).
+     *
+     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+     * @param bool                                                   $absolute Get the absolute of the difference
+     *
+     * @return float
+     */
+    public function floatDiffInWeeks($date = null, $absolute = true)
+    {
+        return $this->floatDiffInDays($date, $absolute) / static::DAYS_PER_WEEK;
+    }
+
     /**
      * Get the difference in months as float (microsecond-precision).
      *
@@ -624,6 +636,19 @@ public function floatDiffInRealDays($date = null, $absolute = true)
         return ($hoursDiff < 0 ? -1 : 1) * $this->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
     }
 
+    /**
+     * Get the difference in weeks as float (microsecond-precision).
+     *
+     * @param \Carbon\CarbonInterface|\DateTimeInterface|string|null $date
+     * @param bool                                                   $absolute Get the absolute of the difference
+     *
+     * @return float
+     */
+    public function floatDiffInRealWeeks($date = null, $absolute = true)
+    {
+        return $this->floatDiffInRealDays($date, $absolute) / static::DAYS_PER_WEEK;
+    }
+
     /**
      * Get the difference in months as float (microsecond-precision) using timestamps.
      *


Test patch:
diff --git a/tests/Carbon/DiffTest.php b/tests/Carbon/DiffTest.php
index aa6188f0c9..4ef7035c72 100644
--- a/tests/Carbon/DiffTest.php
+++ b/tests/Carbon/DiffTest.php
@@ -1560,6 +1560,7 @@ public function testFloatDiff()
         $this->assertSame(8986.665965, Carbon::parse('2018-03-31 23:55:12.321456')->floatDiffInSeconds(Carbon::parse('2018-04-01 02:24:58.987421')));
 
         $this->assertSame(1.0006944444444443, Carbon::parse('2018-12-01 00:00')->floatDiffInDays(Carbon::parse('2018-12-02 00:01')));
+        $this->assertSame(1.0006944444444443 / 7, Carbon::parse('2018-12-01 00:00')->floatDiffInWeeks(Carbon::parse('2018-12-02 00:01')));
 
         $this->assertSame(0.9714742503779745, Carbon::parse('2018-03-13 20:55:12.321456')->floatDiffInMonths(Carbon::parse('2018-04-12 14:24:58.987421')));
         $this->assertSame(1.1724137931034484, Carbon::parse('2000-01-15 00:00')->floatDiffInMonths(Carbon::parse('2000-02-20 00:00')));
@@ -1604,6 +1605,7 @@ public function testFloatDiffWithRealUnits()
         date_default_timezone_set('UTC');
 
         $this->assertSame(1.0006944444444443, Carbon::parse('2018-12-01 00:00')->floatDiffInRealDays(Carbon::parse('2018-12-02 00:01')));
+        $this->assertSame(1.0006944444444443 / 7, Carbon::parse('2018-12-01 00:00')->floatDiffInRealWeeks(Carbon::parse('2018-12-02 00:01')));
 
         $this->assertSame(0.9714742503779745, Carbon::parse('2018-03-13 20:55:12.321456')->floatDiffInRealMonths(Carbon::parse('2018-04-12 14:24:58.987421')));
         $this->assertSame(0.9714742503779745, Carbon::parse('2018-04-12 14:24:58.987421')->floatDiffInRealMonths(Carbon::parse('2018-03-13 20:55:12.321456')));
diff --git a/tests/CarbonImmutable/DiffTest.php b/tests/CarbonImmutable/DiffTest.php
index c8ab59ffa1..b4e8f95aee 100644
--- a/tests/CarbonImmutable/DiffTest.php
+++ b/tests/CarbonImmutable/DiffTest.php
@@ -1541,6 +1541,7 @@ public function testFloatDiff()
         $this->assertSame(8986.665965, Carbon::parse('2018-03-31 23:55:12.321456')->floatDiffInSeconds(Carbon::parse('2018-04-01 02:24:58.987421')));
 
         $this->assertSame(1.0006944444444443, Carbon::parse('2018-12-01 00:00')->floatDiffInDays(Carbon::parse('2018-12-02 00:01')));
+        $this->assertSame(1.0006944444444443 / 7, Carbon::parse('2018-12-01 00:00')->floatDiffInWeeks(Carbon::parse('2018-12-02 00:01')));
 
         $this->assertSame(0.9714742503779745, Carbon::parse('2018-03-13 20:55:12.321456')->floatDiffInMonths(Carbon::parse('2018-04-12 14:24:58.987421')));
         $this->assertSame(0.9714742503779745, Carbon::parse('2018-04-12 14:24:58.987421')->floatDiffInMonths(Carbon::parse('2018-03-13 20:55:12.321456')));
@@ -1582,6 +1583,7 @@ public function testFloatDiffWithRealUnits()
         date_default_timezone_set('UTC');
 
         $this->assertSame(1.0006944444444443, Carbon::parse('2018-12-01 00:00')->floatDiffInRealDays(Carbon::parse('2018-12-02 00:01')));
+        $this->assertSame(1.0006944444444443 / 7, Carbon::parse('2018-12-01 00:00')->floatDiffInRealWeeks(Carbon::parse('2018-12-02 00:01')));
 
         $this->assertSame(0.9714742503779745, Carbon::parse('2018-03-13 20:55:12.321456')->floatDiffInRealMonths(Carbon::parse('2018-04-12 14:24:58.987421')));
         $this->assertSame(0.9714742503779745, Carbon::parse('2018-04-12 14:24:58.987421')->floatDiffInRealMonths(Carbon::parse('2018-03-13 20:55:12.321456')));