18

When upgrading to PHP 8.1, I got an error regarding "strftime". How do I correct the code to correctly display the full month name in any language?

 $date = strftime("%e %B %Y", strtotime('2010-01-08'))
novaidea
  • 301
  • 1
  • 2
  • 5

8 Answers8

9

To my dear and late strftime()... I found a way to adapt with IntlDateFormatter::formatObject and here is the link for the references to the schemas:

https://unicode-org.github.io/icu/userguide/format_parse/datetime/#date-field-symbol-table

... For those who want to format the date more precisely

// "date_default_timezone_set" may be required by your server
date_default_timezone_set( 'Europe/Paris' );

// make a DateTime object 
// the "now" parameter is for get the current date, 
// but that work with a date recived from a database 
// ex. replace "now" by '2022-04-04 05:05:05'
$dateTimeObj = new DateTime('now', new DateTimeZone('Europe/Paris'));

// format the date according to your preferences
// the 3 params are [ DateTime object, ICU date scheme, string locale ]
$dateFormatted = 
IntlDateFormatter::formatObject( 
  $dateTimeObj, 
  'eee d MMMM y à HH:mm', 
  'fr' 
);

// test :
echo ucwords($dateFormatted);

// output : Jeu. 7 Avril 2022 à 04:56
8ctopus
  • 2,617
  • 2
  • 18
  • 25
  • Finally I went a little deeper into the subject and it is better to let the native function manage things, I created a function for myself, maybe to improve but for my needs it covers all the cases, this function is here : https://stackoverflow.com/questions/72435485/php-intldateformatter-remove-day-from-the-date-format/72561375#72561375 – SNS - Web et Informatique Jun 09 '22 at 13:49
  • There is a problem with accents. Try the date 2023-02-01 00:00:59 : you will have : Mercredi 1 Février 2023 00:00:59 How to solve this, please ? – BlueMan Feb 02 '23 at 03:39
  • add into the .. and maybe too on your html code or use a PHP function : ex. $dateFormatted = mb_convert_encoding($dateFormatted, "UTF-8"); – SNS - Web et Informatique Feb 07 '23 at 10:48
7

I've chosen to use php81_bc/strftime composer package as a replacement.

Here the documentation.

Pay attention that the output could be different from native strftime 'cause php81_bc/strftime uses a different library for locale aware formatting (ICU).

Note that output can be slightly different between libc sprintf and this function as it is using ICU.

nulll
  • 1,465
  • 1
  • 17
  • 28
3

You can use the IntlDateFormatter class. The class works independently of the locales settings. With a function like this

function formatLanguage(DateTime $dt,string $format,string $language = 'en') : string {
    $curTz = $dt->getTimezone();
    if($curTz->getName() === 'Z'){
      //INTL don't know Z
      $curTz = new DateTimeZone('UTC');
    }

    $formatPattern = strtr($format,array(
        'D' => '{#1}',
        'l' => '{#2}',
        'M' => '{#3}',
        'F' => '{#4}',
      ));
      $strDate = $dt->format($formatPattern);
      $regEx = '~\{#\d\}~';
      while(preg_match($regEx,$strDate,$match)) {
        $IntlFormat = strtr($match[0],array(
          '{#1}' => 'E',
          '{#2}' => 'EEEE',
          '{#3}' => 'MMM',
          '{#4}' => 'MMMM',
        ));
        $fmt = datefmt_create( $language ,IntlDateFormatter::FULL, IntlDateFormatter::FULL,
        $curTz, IntlDateFormatter::GREGORIAN, $IntlFormat);
        $replace = $fmt ? datefmt_format( $fmt ,$dt) : "???";
        $strDate = str_replace($match[0], $replace, $strDate);
      }

    return $strDate;
}

you can use format parameters like for datetime.

$dt = date_create('2022-01-31');
echo formatLanguage($dt, 'd F Y','pl');  //31 stycznia 2022

There are extension classes for DateTime that have such functions integrated as methods.

echo dt::create('2022-01-31')->formatL('d F Y','pl');
jspit
  • 7,276
  • 1
  • 9
  • 17
3

The strftime is obsolete and DateTime::format() provide a quick replacement and IntlDateFormatter::format() provied a more sophisticated slution.

this links will be help you:

https://github.com/modxcms/revolution/issues/15864

https://github.com/php/php-src/blob/1cf4fb739f7a4fa8404a4c0958f13d04eae519d4/UPGRADING#L379-L381

https://www.php.net/manual/en/datetime.format.php

Milad pegah
  • 321
  • 1
  • 8
  • 3
    `DateTime::format` cannot be used for that purpose as it only outputs English. See php.net doc under Notes. – 8ctopus May 17 '22 at 10:16
0

strftime is deprecated PHP 8.1, You can use date function.

$date = date("%e F Y", strtotime('2010-01-08'))
  • Note for users that are using `setlocale()` function: `date()` is only able to return month/day names in english, even if you changed your `setlocale()` – mattja Mar 15 '23 at 19:27
0

I made a script that defines strftime() function if it does not exist. Note that this is solution for already existing programming codes which are based on strftime(). For new code works you should forget using strftime() function.

https://github.com/sunhater/strftime

Pavel Tzonkov
  • 264
  • 3
  • 9
-2

Hey I have also experienced this issue as well so after some research on PHP's official documentation here what I found! https://www.php.net/manual/en/function.strftime.php
They are saying that it is depricated and use setlocale() function this also work same as strftime().
For more information please visit official PHP docs of setlocale() https://www.php.net/manual/en/function.setlocale.php

-2

A quick and simple replacement for the deprecated function strftime can be following.

Instead of using (taking the sample from the question)

$date = strftime("%e %B %Y", strtotime('2010-01-08'))

convert that to:

$date = date('d M Y', strtotime('2010-01-08')

OSWorX
  • 136
  • 9