human_readable_duration, ou pas ?
Ceci est un post réaction suite à un tweet de notre ami Pierre (on adore tes tweets WPro-Tips !!)
[WPost-It] 🕙Besoin de transformer "02:15" ou "25:48" en une durée lisible et traduisible ? Utilisez human_readable_duration() ! pic.twitter.com/EXjQnp0iDk
— Pierre Saïkali (@psaikali) February 26, 2020
deux points
Alors déjà ma question est : quand/où obtient-on une donnée de temps sous ce format ?
49:18:27
Je vais vous le dire : dans les meta données des fichiers vidéos ou audio, c’est tout.
Donc autant c’est sympa, autant je trouve que son usage est plutôt réduit.
human
Et si on voulait l’utiliser pour autre chose justement car c’est ça le but, pouvoir utiliser l’existant ailleurs !
Disons que je souhaite afficher une longue durée, au delà de 24 heures ?
Perso, j’aurais aimé que ça passe en jours, ça c’est humain :/ Et aussi que la dernière virgule soit plutôt un « et ». Non je ne suis pas tatillon, c’est du natif WordPress si on utilise wp_sprintf_l()
! Je trouve ça plus propre.
seconde
Mais surtout, quand je dis « ailleurs », eh bien je récupère 99% du temps des secondes, le fameux 314638200
par exemple.
Mais cette fonction ne prend QUE un format bien précis, avec des secondes et minutes qui ne dépassent pas 59, et les heures illimitées mais pas de jours.
Je souhaite alors obtenir le même résultat que human_readable_duration()
mais en lui passant juste des secondes.
bonus x5
Car j’aime rajouter des options, je souhaite :
- ne pas afficher si besoin les valeurs qui sont à 0,
- afficher les majuscules sur les jours ou pas,
- ne pas recréer de traductions, juste du natif,
- garder une compat avec le format vidéo/audio même s’il dépasse les limites comme « 99:99:99:99:99 »,
- pouvoir dépasser jusque 999 ans !
Le tout en natif WordPress, code optimisé et propre bien entendu.
code commenté
full options air bag à l’arrière
code plus light
sans les caps, sans les 0, sans commentaires
Quelques explications
Avant les exemples.
- J’utilise
is_numeric()
et nonis_int()
ouintval()
comme ça on peut aussi bien passer une chaine de chiffres ou un chiffre (voir les exemples). - Les coefficients sont les constantes de WordPress, rien à déclarer !
- Je fais un explode avec
:
car c’est le format attendu, je force là unintval()
pour mettre à 0 les possibles chaines de texte et éviter des erreurs par la suite (je ne patche pas la connerie), et je reverse le tout car je vais commencer à compter par les secondes (je ne peux pas commencer par les années, il n’y en a peut-être pas !) et remonter. - Je calcule donc mon nombre de secondes en additionnant en boucle le produit de mes coefficients. j’obtient alors naturellement un nombre de secondes depuis une chaine comme
49:18:27
! - Si jamais on a 0 dans
$entry
, alors c’est qu’on a passé en paramètre du texte… Si vous passez un array ça fera surement pire, mais encore une fois, je ne patche pas la connerie ! - Maintenant qu’on a un entier, on peut commencer le vrai travail, créer une chaine qui se découpe toute seule, pas de math à faire avec des divisions par 60, 30, 24, 365 pour savoir si on a des jours, mois, années, minutes… alors que PHP fait ça nativement !
- On a donc ce format :
'%s:%i:%h:%d:%m:%y'
qui va des secondes au années. S’il n’y a pas d’années, ça vaut alors 0 tout simplement ! - Je déclare des labels qui proviennent de WP lui même, rien à retraduire, magiiiiie. Et j’utilise
_n_noop()
car je dois gérer le cas des pluriels selon la langue locale, et je ne sais pas encore combien est la valeur, donc je ne peux pas décider. - Là selon les paramètres, on laisse passer ou pas pour avoir les valeurs à 0 (voir les exemples). Ce qui est intéressant est le check avec
array_map( $return, 'intval' )
, le but est de n’ajouter les valeurs que si ce n’est pas vide, sans compter les 0 qui sont à la fin, pour le param « last » donc. Leintval
sur les valeurs comme « 0 secondes » va retourner « 0 » et donc va supprimer le temps du test car 0 == false ! - Puis pour chaque de nos données de temps, on va enfin chercher la bonne trad avec le bon pluriel. C’est là qu’on utilise
translate_nooped_plural()
pour enfin mettre le compteur qui va alors nous donner le singulier ou pluriel. - Rapidement on fait un
ucwords()
sur notre valeur pour la majuscule (on aurait aussi pu le faire à la fin avec unarray_map()
). - Nous voila à la fin, on reverse de nouveau le tableau pour lire des années vers les secondes, humain quoi.
- Et là, la grande magie opère avec l’appel à wp_sprintf_l() qui va nous retourner une chaine concaténée avec des virgules comme un
implode( ', ' )
mais avec la petite particularité d’avoir une virgule de série (aussi appelée virgule d’Oxford ou Oxford comma) avec son « et » tout beau (voir les exemples).
example.com
Comparons d’abord des appels que human_readable_duration sait gérer :
Bon, c’est le seul cas qu’il sait gérer, et il ne gère pas les jours…
À nous, voici ce qu’on peut obtenir :
Voilà, ça c’est utilisable ! Qu’on y passe des valeurs entières, des chaines de chiffres, du format de durée même avec de grands nombres, tout va bien !
D’ailleurs, on devrait réécrire human_readable_duration
pour remettre ça au clair, car rien que le début, je ne comprends pas :
Mettre un paramètre avec une valeur par défaut vide et devoir gérer le cas où on a rien mis en paramètre alors qu’il suffisait de ne pas mettre de valeur par défaut pour que PHP fasse lui même l’erreur !? WHAT?
La gestion du tiret négatif devrait se faire en amont et pas à elle de faire ça.
Ça fait du preg_match
pour patcher la connerie au lieu de balancer du 0 avec intval
.
1 IF pour chaque entrée, sinon, des boucles ? non ok…
BREF j’aime retoucher du code 😉
Réagir à cet article