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

Created on 17 February 2022, almost 3 years ago
Updated 18 December 2023, about 1 year ago

Problem/Motivation

Per https://wiki.php.net/rfc/implicit-float-int-deprecate, as of PHP8.1, type coercion of a float-like variable to integer will result in a PHP E_DEPRECATED and become TypeError in PHP9.

As of 2023-05, The Drupal\Component\Datetime::createFromTimestamp does not declare a type for its $timestamp parameter and relies on using an is_numeric check, however this does not prevent the float-to-int deprecation case from happening.

Steps to reproduce

This has been documented in contrib projects:

ultimate_cron

Deprecated function: Implicit conversion from float-string to int loses precision in Drupal\Component\Datetime\DateTimePlus->__call()
Drupal\Component\Datetime\DateTimePlus->__call('setTimestamp', Array) (Line: 204)
Drupal\Component\Datetime\DateTimePlus::createFromTimestamp(, Object, Array) (Line: 122)
Drupal\Core\Datetime\DateFormatter->format(, 'short') (Line: 52)
Drupal\ultimate_cron\CronJobListBuilder->buildRow(Object) (Line: 126)
Drupal\Core\Config\Entity\DraggableListBuilder->buildForm(Array, Object)

https://www.drupal.org/project/drupal/issues/3264979#comment-14531035 🐛 Deprecated function: Implicit conversion from float-string to int loses precision in Drupal\Component\Datetime\DateTimePlus Needs work

migrate_tools
https://www.drupal.org/project/drupal/issues/3264979#comment-14642373 🐛 Deprecated function: Implicit conversion from float-string to int loses precision in Drupal\Component\Datetime\DateTimePlus Needs work

Proposed resolution

Current state of MR + patches is to cast the $timestamp variable to an integer but not change the method parameter type.

Comment #28 🐛 Deprecated function: Implicit conversion from float-string to int loses precision in Drupal\Component\Datetime\DateTimePlus Needs work suggests declaring int $timestamp and rely on typechecking.

Remaining tasks

Decide on more strict type declaration for the ::createFromTimestamp method param.

User interface changes

API changes

TBD

Data model changes

Release notes snippet

🐛 Bug report
Status

Needs work

Version

11.0 🔥

Component
Datetime 

Last updated 2 days 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.

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 almost 2 years ago
  • 🇨🇴Colombia anacona16

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

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

    Still needs tests though

  • First commit to issue fork.
  • @voleger opened merge request.
  • Status changed to Needs review almost 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 almost 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 over 1 year 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 over 1 year 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 over 1 year 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 Princeton, NJ

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

  • 🇺🇸United States angrytoast Princeton, NJ

    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 over 1 year ago
    Custom Commands Failed
  • 🇨🇱Chile lathan Chile

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

  • 🇺🇸United States angrytoast Princeton, NJ

    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

Production build 0.71.5 2024