Jump to content

strftime deprecation


monollonom
 Share

Recommended Posts

Hi,

I know quite a few of us are working on multi-language websites and are most likely using the `strftime`, however it's deprecated as of 8.1.0 and set to be removed in 9.0. There's some time left but on my local environment using MAMP and 8.0.8, it's as if it's already gone as dates were not localized anymore. Looking for options, I came accross this which might be useful to others: https://gist.github.com/bohwaz/42fc223031e2b2dd2585aab159a20f30

What's your take on this ? Also I wonder how things will be handled in PW's core as the WireDateTime is using that function as well.

  • Like 6
Link to comment
Share on other sites

I have no take on this (yet!) but since I am using the strftime function a lot I better get used to a solution for the future.

The library you postet here https://github.com/alphp/strftime looks promising enough, the "old" strftime code needs to be altered just with the locale and it works good for me:

<?= strftime('%e. %B', strtotime('now'), 'de_DE'); ?>

The "offical" solution seems to use the IntlDateFormatter::format, but I find the usage is nowhere as straight forward as with strftime... https://www.php.net/manual/en/intldateformatter.format.php

  • Like 1
Link to comment
Share on other sites

2 hours ago, Stefanowitsch said:

The "offical" solution seems to use the IntlDateFormatter::format, but I find the usage is nowhere as straight forward as with strftime... https://www.php.net/manual/en/intldateformatter.format.php

Yeah my thought exactly... though it might be because it's my first time encountering it.

My understanding is that it harmonizes with its javascript counterpart (that I never used lol) and it might be good for common cases, but if you want to have something more custom then you either have to write a lot of stuff or use the nice(r) alternative listed above.

Link to comment
Share on other sites

So i tried the other way around and formatted a date using the IntlDateFormatter.

This thread helped me find my way: https://stackoverflow.com/questions/71874030/local-language-without-strftime-deprecated-but-with-date

So imagine we want to output "today" like this (formatted for german) 

Mittwoch 8 Juni 2022

This was the old way to to it:

echo strftime('%A %e %B %Y', strtotime('now'));

Since this will be deprecated in PHP 8.1 and removed in PHP 9 now we have to make use of this instead:

$fmt = new IntlDateFormatter('de_DE',
  IntlDateFormatter::FULL,
  IntlDateFormatter::FULL
);
$fmt->setPattern('EEEE d LLLL yyyy');
echo $fmt->format(strtotime("now"));

The only thing that freaked my out about this was the weird formatting pattern. At first sight it makes no sense (to me), but the ICU documentation offers a big list of available options for formatting the date in any way you could imagine:

https://unicode-org.github.io/icu/userguide/format_parse/datetime/

If you are looking for a "one liner solution" then this seems to be the right way (https://stackoverflow.com/questions/12038558/php-timestamp-into-datetime)

echo IntlDateFormatter::formatObject( new DateTime('@' . strtotime("now")), "EEEE d LLLL yyyy", 'de_DE' );

EDIT: Beware that timezone settings get ignored when you work with timestamps. This might get you into some trouble. 
My solution was to format the timestamp into a date string:

echo IntlDateFormatter::formatObject( new DateTime(date("d.m.Y", $timestamp)), "EEEE d LLLL yyyy", 'de_DE' );

 

  • Like 8
Link to comment
Share on other sites

  • 8 months later...

@Stefanowitsch

thanks for your input here...

After I worked for years with the combination "setlocale" & "strftime", I realize today through my intelephense that strftime is DEPRECATED. So I went looking for a successor and ended up here with your article.

I like the one-liner very much! I had to adapt it only a little, because I got otherwise errors with the classes and with the format of the date...

Therefore here my adapted version...

echo \IntlDateFormatter::formatObject( new \DateTime(date("d.m.Y", $page->getUnformatted('date'))), "EE dd.MM.YYYY", 'de_DE' );

 

  • Like 2
Link to comment
Share on other sites

Hi,

I need your help 😉

I try to display date/time info in a multi-language processwire setting. 

Can you please indicate me which of the above solutions will work to display the different date/time formats on the respective lang page. At the moment the Date is only rendered the way I want in German but not on the English page. (My output for my date field in the backend is not formatted.)

The code below gives me this results:
German: Sa., 4. März 2023, 09:00
English: 2023/03/04 09:00:00

 

$datum = $concert->date;
 
$fmt = new \IntlDateFormatter('DE',
\IntlDateFormatter::FULL
);
$fmt->setPattern('E, d. LLLL yyyy, HH:mm');
echo $fmt->format($datum);
Link to comment
Share on other sites

@Thomas -Allwinds Webstudio when creating your IntlDateFormatter, do you set the locale based on the user’s language or is hard-coded like in your code sample?

It depends on how you named your languages or which one is your default but maybe it could be:

$datum = $concert->date;
 
$fmt = new \IntlDateFormatter($user->language->isDefault() ? "en_US" : "de-DE",
    \IntlDateFormatter::FULL
);
$fmt->setPattern('E, d. LLLL yyyy, HH:mm');
echo $fmt->format($datum);

 

Link to comment
Share on other sites

1 hour ago, monollonom said:

@Thomas -Allwinds Webstudio when creating your IntlDateFormatter, do you set the locale based on the user’s language or is hard-coded like in your code sample?

It depends on how you named your languages or which one is your default but maybe it could be:

$datum = $concert->date;
 
$fmt = new \IntlDateFormatter($user->language->isDefault() ? "en_US" : "de-DE",
    \IntlDateFormatter::FULL
);
$fmt->setPattern('E, d. LLLL yyyy, HH:mm');
echo $fmt->format($datum);

 

I use the multi-lang template that pw provides. And I did not check this as the language switcher worked fine until now that I have this issue with the date formatting. I actually set the html lang element to the current lang of the page. Does this help?

Link to comment
Share on other sites

You mean the multi-lang site profile? I assume your default language is English then, did you try the code I gave you? The important part is replacing

new \IntlDateFormatter('DE',

with:

new \IntlDateFormatter($user->language->isDefault() ? "en_US" : "de-DE"

And if it happens to be the wrong way around, just invert "en" and "de".

  • Like 1
Link to comment
Share on other sites

Ah - this works: thanks a lot! - yes I had to change the default to de-DE; but works fine - what would the solution be, if it were a site with 3 different languages?

Or when I would like not only to have the correct translation for month but also a different pattern for German and English (i.E. 1. Jan. 2023 vs. 1st of jan. 2023

Link to comment
Share on other sites

In this case, best is to simply go with either an "if" or "switch" statement, something like:

$datum = $concert->date;

$format = "E, d. LLLL yyyy, HH:mm";
switch($user->language->name) {
	case "deutsch":
		$lang = "de-DE";
		$format = "EE dd.MM.YYYY";
		break;
	case "français":
		$lang = "fr_FR";
		break;
	case "default":
		$lang = "en_US";
		break;
}

$fmt = new \IntlDateFormatter($lang, \IntlDateFormatter::FULL);
$fmt->setPattern($format);
echo $fmt->format($datum);
  • Like 2
Link to comment
Share on other sites

  • 2 months later...

Maybe this can help. It work like the original `$datetime->formatDate()` Method.

wire()->addHookMethod('WireDateTime::formatIntlDate', function(HookEvent $event) {

	$value = $event->arguments(0);
	$format = htmlspecialchars_decode($event->arguments(1), ENT_QUOTES); // support placeholder in time format like 'o''clock'

	if(!$value) { $event->return = ''; return; }
	if(!strlen("$format")) { $event->return = (int) $value; return; } // unix timestamp

	// create datetime
	$dt = \DateTime::createFromFormat('U', (int) $value);
	if(!($dt instanceof \DateTime)) { $event->return = (int) $value; return; }

	// set timezone
	if($this->config->timezone) $dt->setTimezone(new \DateTimeZone($this->config->timezone));

	// locale
	$locale = setlocale(LC_TIME, 0);

	// format
	$event->return = \IntlDateFormatter::formatObject($dt, $format, $locale);
});

echo $datetime->formatIntlDate(1678010433, \IntlDateFormatter::LONG);
// March 5, 2023 at 11:00:33 AM GMT+1 (en_US)
// 5 March 2023 at 11:00:33 CET (en_GB)
// 5. März 2023 um 11:00:33 MEZ (de_DE)

echo $datetime->formatIntlDate(1687453200, __("ccc, d. MMM y hh:mm a"));
// Thu, 22. Jun 2023 07:00 PM (en_US)
// Translated in German: "ccc, d. MMM y kk:ss 'Uhr'"
// Do, 22. Juni 2023 19:00 Uhr (de_DE)

You can find all date field symbols here: https://unicode-org.github.io/icu/userguide/format_parse/datetime/#date-field-symbol-table

Link to comment
Share on other sites

As strftime is deprecated and it‘s alternative is a bit overshoot to me, I tend to just create an associative array with the short Weekday names like $shortWeekdays = array(1 => 'Mo.', 2 => 'Di.', …, 7 => 'So.'); and access them like $shortWeekdays[date('w', (int) $page->getUnformatted('datefield'))];

Just put this stuff in my _init.php file so I can use it where I need it in the template files. If I would need multilingual support, I would create an associative array with the required language codes like array('de' => array(1 => 'Mo.', …), 'en' => array(1 => 'Mon.', …));

Link to comment
Share on other sites

Hey! A client wanted me to update their website to make it show dates in the form "1. - 3. Jän. 2023" instead of "1. Jän. 2023 - 3. Jän. 2023"

It's a small change but not so easy to solve, especially if you want to make it locale aware etc...

So I've created "HumanDates" library which is not a PW module but a standalone PHP class so that everybody can easily use it even outside of the PW universe: https://github.com/baumrock/HumanDates

Usage is simple and the library can be used as a strftime replacement:

// manual download
require_once "/path/to/HumanDates.php";

// using composer
// composer require baumrock/humandates
require_once "/path/to/composer/autoload.php";

// create HumanDates instance
$dates = new HumanDates();
echo $dates->format("2023-01-01");              // 1. Jan 2023
echo $dates->range("2023-01-01", "2023-01-03"); // 1. - 3. Jan 2023

If it is useful to you please let me know by giving it a star on github 🙂 https://github.com/baumrock/HumanDates/stargazers

PS: It will be available in RockFrontend in the next release simply by calling $rockfrontend->humandates() 😎

  • Like 14
Link to comment
Share on other sites

  • monollonom changed the title to strftime deprecation
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...