monollonom Posted June 6, 2022 Share Posted June 6, 2022 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. 6 Link to comment Share on other sites More sharing options...
Stefanowitsch Posted June 8, 2022 Share Posted June 8, 2022 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 1 Link to comment Share on other sites More sharing options...
monollonom Posted June 8, 2022 Author Share Posted June 8, 2022 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 More sharing options...
Stefanowitsch Posted June 8, 2022 Share Posted June 8, 2022 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' ); 8 Link to comment Share on other sites More sharing options...
Ralf Posted February 27, 2023 Share Posted February 27, 2023 @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' ); 2 Link to comment Share on other sites More sharing options...
Thomas -Allwinds Webstudio Posted March 6, 2023 Share Posted March 6, 2023 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 More sharing options...
monollonom Posted March 6, 2023 Author Share Posted March 6, 2023 @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 More sharing options...
Thomas -Allwinds Webstudio Posted March 6, 2023 Share Posted March 6, 2023 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 More sharing options...
monollonom Posted March 6, 2023 Author Share Posted March 6, 2023 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". 1 Link to comment Share on other sites More sharing options...
Thomas -Allwinds Webstudio Posted March 6, 2023 Share Posted March 6, 2023 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 More sharing options...
monollonom Posted March 6, 2023 Author Share Posted March 6, 2023 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); 2 Link to comment Share on other sites More sharing options...
Thomas -Allwinds Webstudio Posted March 7, 2023 Share Posted March 7, 2023 Thanks - for this detailed solution which is for sure a good base for all needs on this behalf. and works fine for my requirements. Link to comment Share on other sites More sharing options...
Neue Rituale Posted June 5, 2023 Share Posted June 5, 2023 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 More sharing options...
cwsoft Posted June 11, 2023 Share Posted June 11, 2023 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 More sharing options...
bernhard Posted June 13, 2023 Share Posted June 13, 2023 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() ? 14 Link to comment Share on other sites More sharing options...
eydun Posted July 15, 2023 Share Posted July 15, 2023 I just tried HumanDates for the first time. Wow, this is a package I have been missing for many years, thanks! 1 Link to comment Share on other sites More sharing options...
Recommended Posts