1
\$\begingroup\$

I'm trying to find a good way to dynamically print a selection of localized days of week without resorting to an hard-coded array per language, leveraging locale mechanisms instead.

Up until now, I've tried 2 methods which both have their weaknesses.

Input Example :

$dows_input = array(0, 1, 2, 4, 6);

Which represent Sunday, Monday, Tuesday, Thursday and Saturday values. Those are not necessary always the same days on each call.

NB : Which locale is used is simplified in our methods below, as it's normally coming from a session variable depending on the end-user language setting.

Method 1 : via setlocale + strftime

function via_setlocale($dows_input) {
  $defaultLocale = Locale::getDefault();
  $days = "";
  foreach($dows_input as $dow) {
    setlocale(LC_TIME, "fr_CA.utf8"); //Either set this for a Unix-based server
    //setlocale(LC_TIME, "french"); //Or this for a Windows server
    $t = strftime('%A', strtotime('next Sunday +' . $dow . ' days'));
    setlocale(LC_TIME, $defaultLocale);
    $days .= $t . ",";
  }
  return substr($days, 0, -1);
}

Method 2 : VIA IntlDateFormatter

function via_dateformatter($dows_input) {
  $formatter = new IntlDateFormatter(
                'fr_CA',
                IntlDateFormatter::NONE,
                IntlDateFormatter::NONE,
                DateTimeZone::UTC,
                IntlDateFormatter::GREGORIAN,
                'EEEE' //Day of the week, localized, complete
              );
  $days = array_map(
    function($dow) use($formatter) {
        return $formatter->format(strtotime('next Sunday +' . $dow . ' days'));
    },
    $dows_input
  );
  return implode(",", $days);
}

Method 1 comes with the usual problems associated with setlocale in a multi-threaded environment as it is per process, leading to unpredictable behaviours if not called and reset on every call to a locale-based function.

Method 2 takes about 3 to 4 times longer to execute from my tests than Method 1, but is thread-safe. Intl extension must be available on the host system.

As for now I've opted for a single call to Method 2 (with a fallback to Method 1 if extension is not available) with all days of the week stocked in memory once through the whole request, so the speed factor is less of a issue over different $dow_inputs.

Any thoughts on how to make this better? Is there another alternative I have not thought of you could share? Bonus point for the more portable solution out there, as it is meant to run on multiple typical, run-of-the-mill shared hosting servers with PHP 5.3+ environments.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.