2016-02-12 2 views
1

Je pensais avoir trouvé la meilleure solution pour une solution de contournement pour PHP strftime() sur Windows, puis un utilisateur a signalé un problème.Contournement de l'encodage de charset pour strftime() sous Windows?

Windows a certaines limitations à strftime() et en outre il ne prend pas en charge UTF-8. J'ai donc écrit une solution de contournement pour ces deux problèmes, mais trébucher sur les problèmes de jeu de caractères.

C'est ce que mon code ressemble à:

function strftimefixed($format, $timestamp=null) { 

    if ($timestamp === null) $timestamp = time(); 

    if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { 
    $format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format); // Don't mind this line 
    } 

    return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'auto'); // Charset is the problem 
} 

Message d'erreur

Attention: mb_convert_encoding(): Impossible de détecter le codage des caractères

Comme vous pouvez le voir « auto 'échoue à identifier l'encodage. L'utilisateur est sur une installation Windows, mais je ne peux pas le coder en 'ISO-8859-2' car cela aidera seulement les utilisateurs tchèques et pas les autres utilisateurs finaux qui n'ont pas la moindre idée de ce qu'est un environnement Windows. ou par quel charset.

Alors, quelle est la meilleure solution pour faire une solution de contournement universelle?

Remarque: Le format n'est pas le problème ici. Cela pourrait être n'importe quoi, comme% b% e% Y% H:% M. L'identification du charset est le problème.

+0

Vous pouvez utiliser mb_detect_encoding()? Les docs PHP.net ont des exemples :) [ici] (http://php.net/manual/fr/function.mb-detect-encoding.php) – pxgamer

+0

mb_detect_encoding() fonctionnerait-il différemment de mb_convert_encoding (... , ..., 'auto')? – tim

+0

Eh bien, il vous permettrait de détecter l'encodage qu'il est actuellement, alors vous pouvez convertir. Bien que, il peut être préférable d'avoir juste une liste déroulante qui sélectionne le pays dans lequel vous êtes (base alors l'encodage sur cela). – pxgamer

Répondre

0

Selon the manual, les questions qui strftime() a sous Windows comprennent:

Tous les indicateurs de conversion peuvent être pris en charge par votre bibliothèque C, dans auquel cas ils ne seront pas pris en charge par PHP de strftime(). En outre, toutes les plates-formes ne prennent pas en charge les horodatages négatifs, donc votre plage de dates peut être limitée à au plus tôt à l'époque Unix. Ce signifie que% e,% T,% R et,% D (et éventuellement d'autres) - ainsi que les dates avant le 1er janvier 1970 - ne fonctionneront pas sous Windows, certaines distributions Linux , et quelques autres systèmes.

Votre code utilise des paramètres non divulgués ($format et $timestamp) donc ce que vous inquiète est assez floue.

Toutefois, le message d'erreur que vous obtenez est associé à le codage de texte, pas la gestion de la date en soi. Il est tout simplement impossible de gérer correctement le texte pour les codages inconnus, mais vous pouvez choisir l'encodage produit par strftime() en sélectionnant un lieu approprié:

strftime - Formate une date/heure locale selon les paramètres régionaux

Formatez l'heure et/ou la date en fonction des paramètres régionaux. Les noms de mois et de jour et les autres chaînes dépendantes de la langue respectent les paramètres régionaux actuels définis avec setlocale().

Prenez garde cependant que la manipulation des paramètres régionaux ne sont pas fiables dans certaines plateformes telles que thread-safe construit sur Windows. Si c'est le cas, vous devrez peut-être vider complètement strftime() et choisir un outil de localisation approprié.

Bien sûr, vous pouvez toujours laisser les paramètres régionaux par défaut et essayer d'en deviner l'encodage, mais vous aurez probablement besoin de gérer une base de données.

+0

Il est défini sur setlocale ('czech') sur Windows où, dans ce cas, ISO-8859-2 est l'encodage. Mais les utilisateurs finaux n'en ont aucune connaissance et j'ai besoin d'une solution universelle pour le chinois, le japonais, le cyrillique. Windows ne prend pas en charge UTF-8, donc strftime a besoin d'une solution de contournement. – tim

+0

Je vois que vous avez finalement utilisé mon dernier conseil. Content que cela ait aidé. –

+0

Merci pour votre aide. Je souhaite que la manipulation manuelle de charset ait pu être évitée mais ceci fera. – tim

0

La meilleure solution que je pouvais trouver était de détecter le charset de paramètres régionaux de Windows et de le résoudre à partir de là.

function strftimefixed($format, $timestamp=null) { 

    if ($timestamp === null) $timestamp = time(); 

    if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { 
    $format = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $format); 

    $locale = setlocale(LC_TIME, 0); 

    switch(true) { 
     case (preg_match('#\.(874|1256)$#', $locale, $matches)): 
     return iconv('UTF-8', "$locale_charset", strftime($format, $timestamp)); 

     case (preg_match('#\.1250$#', $locale)): 
     return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'ISO-8859-2'); 

     case (preg_match('#\.(1251|1252|1254)$#', $locale, $matches)): 
     return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'Windows-'.$matches[1]); 

     case (preg_match('#\.(1255|1256)$#', $locale, $matches)): 
     return iconv('UTF-8', "Windows-{$matches[1]}", strftime($format, $timestamp)); 

     case (preg_match('#\.1257$#', $locale)): 
     return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'ISO-8859-13'); 

     case (preg_match('#\.(932|936|950)$#', $locale)): 
     return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'CP'.$matches[1]); 

     case (preg_match('#\.(949)$#', $locale)): 
     return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'EUC-KR'); 

     default: 
     trigger_error("Unknown charset for system locale ($locale)", E_USER_NOTICE); 
     return mb_convert_encoding(strftime($format, $timestamp), 'UTF-8', 'auto'); 
    } 
    } 

    return strftime($format, $timestamp); 
}