Deprecated function: Implicit conversion from float-string <float> to int loses precision in Drupal\Component\Datetime\DateTimePlus

Created on 17 February 2022, about 3 years ago
Updated 16 January 2023, over 2 years ago
Deprecated function: Implicit conversion from float-string <float> to int loses precision in Drupal\Component\Datetime\DateTimePlus->__call()
Drupal\Component\Datetime\DateTimePlus->__call('setTimestamp', Array) (Line: 204)
Drupal\Component\Datetime\DateTimePlus::createFromTimestamp(<float>, Object, Array) (Line: 122)
Drupal\Core\Datetime\DateFormatter->format(<float>, 'short') (Line: 52)
Drupal\ultimate_cron\CronJobListBuilder->buildRow(Object) (Line: 126)
Drupal\Core\Config\Entity\DraggableListBuilder->buildForm(Array, Object)
🐛 Bug report
Status

Needs work

Version

10.1

Component
Datetime 

Last updated about 18 hours ago

Created by

🇧🇪Belgium akasake

Live updates comments and jobs are added and updated live.
  • PHP 8.1

    The issue particularly affects sites running on PHP version 8.1.0 or later.

  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇨🇦Canada smulvih2 Canada 🍁

    #16 works for me on 9.4.9

  • 🇺🇦Ukraine quadrexdev Lutsk

    We also used a patch from #10 on our project and it caused a fatal error: InvalidArgumentException: The timestamp must be numeric. in Drupal\Component\Datetime\DateTimePlus::createFromTimestamp() (line 201 of core/lib/Drupal/Component/Datetime/DateTimePlus.php).

    Applying a patch from #16 fixed this issue. Thanks, @anacona16

  • Status changed to Needs review about 2 years ago
  • 🇨🇴Colombia anacona16

    Based on the merge in #18 the merge passed the tests.

  • Status changed to Needs work about 2 years ago
  • 🇺🇸United States smustgrave

    Still needs tests though

  • First commit to issue fork.
  • @voleger opened merge request.
  • Status changed to Needs review about 2 years ago
  • 🇺🇦Ukraine voleger Ukraine, Rivne

    Added test case with different datatypes of the timestamp passed to the static method.

  • Status changed to RTBC about 2 years ago
  • 🇺🇸United States smustgrave

    Test does cover the scenario.
    Ran locally without the fix and got

    Unsilenced deprecation notices (2)
    
      1x: Implicit conversion from float-string "87654321.1" to int loses precision
        1x in DrupalDateTimeTest::testTimestampArgumentTypes from Drupal\Tests\system\Functional\Datetime
    
      1x: Implicit conversion from float 87654321.1 to int loses precision
        1x in DrupalDateTimeTest::testTimestampArgumentTypes from Drupal\Tests\system\Functional\Datetime
    
  • Status changed to Needs review about 2 years ago
  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    Given this is a public static method it is super tempting to add a typehint to the method and remove the is_numeric check... like

      public static function createFromTimestamp(int $timestamp, $timezone = NULL, $settings = []) {
        $datetime = new static('', $timezone, $settings);
        $datetime->setTimestamp($timestamp);
        return $datetime;
      }
    

    Going to ping release managers and ask for a thought. Also FWIW the calling code could cast to an integer from a float. It shouldn't be passing floats in here. Why is a float being passed in here?

  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    We could tidy up this code in migrate plus to not pass in a float.

            $row['last_imported'] = $date_formatter->format($last_imported / 1000,
              'custom', 'Y-m-d H:i:s');
    

    Because PHP is not going to do the right thing... see https://3v4l.org/HDF4t

  • Status changed to Needs work about 2 years ago
  • 🇺🇸United States smustgrave

    Probably would make the code cleaner to use typehints vs (int) check.

    Tests should still cover that.

  • First commit to issue fork.
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update about 2 years ago
    Custom Commands Failed
  • 🇦🇺Australia dpi Perth, Australia

    Minor formatting.

    Can we improve the issue summary a little? such as with standard template

  • 🇺🇸United States angrytoast PNW

    Per #32, update issue summary with default template and relevant details

  • 🇺🇸United States angrytoast PNW

    I see that the newly added tests are in Functional tests Drupal\Tests\system\Functional\Datetime\DrupalDateTimeTest, however there are already existing unit tests in Drupal\Tests\Component\Datetime\DateTimePlusTest. This looks more appropriate to add to the unit test class as they would be better grouped and much faster?

  • last update almost 2 years ago
    Custom Commands Failed
  • 🇨🇱Chile lathan Chile

    there are a few more references to setTimestamp that have been missed here in this patch

  • Pipeline finished with Failed
    over 1 year ago
    Total: 174s
    #46164
  • Pipeline finished with Failed
    over 1 year ago
    Total: 177s
    #64803
  • 🇺🇸United States angrytoast PNW

    Regarding comments #28-30 that suggest using type hinting, wouldn't this cause issues for code out in the wild that call the method and currently does not cast the first $timestamp parameter? If we go down this route, should it have a BC layer to warn and eventually enforce the parameter strict typing?

    IMO the current approach in https://git.drupalcode.org/project/drupal/-/merge_requests/3254 is more accommodating and would cause less issues for existing implementations.

    Thoughts?

  • When it's the return type, you can use the ReturnTypeWillChange attribute. I don't think there's something similar for parameters.

    Also, this seems relevant: #1158720: [policy, no patch] Add parameter type hinting to function declaration coding standards

  • 🇩🇪Germany tobiasb Berlin

    Fyi: 8.4 comes with native \DateTime::createFromTimestamp, which allows int|float. https://github.com/php/php-src/commit/88f2dc626862b4c40ea20b8029838a8d0d....

    
    $timestamp = 2147483647/1.1;
    
    // Origin float
    var_dump($timestamp);
    
    $timestamp_casted = (int) $timestamp;
    
    // Casted as int
    var_dump($timestamp_casted);
    
    // Output with float
    var_dump(DateTime::createFromTimestamp($timestamp));
    
    // Output with casted float
    var_dump(DateTime::createFromTimestamp($timestamp_casted));
    

    Output in 8.4.6:

    float(1952257860.9090908)
    int(1952257860)
    object(DateTime)#1 (3) {
      ["date"]=>
      string(26) "2031-11-12 13:51:00.909091"
      ["timezone_type"]=>
      int(1)
      ["timezone"]=>
      string(6) "+00:00"
    }
    object(DateTime)#1 (3) {
      ["date"]=>
      string(26) "2031-11-12 13:51:00.000000"
      ["timezone_type"]=>
      int(1)
      ["timezone"]=>
      string(6) "+00:00"
    }

    So the best is to follow php-core.

  • Pipeline finished with Failed
    8 days ago
    Total: 137s
    #486498
  • Pipeline finished with Failed
    8 days ago
    Total: 304s
    #486515
  • 🇩🇪Germany tobiasb Berlin

    Ok, forget it. setTimestamp wants a int. Unless we are calling the origin DateTime::createFromTimestamp in >= php8.4.

    I move the test to the unit test.

  • Pipeline finished with Success
    8 days ago
    Total: 960s
    #486524
Production build 0.71.5 2024