[SPIP] v3.2.12 -> v3.2.12 - Reinstallation avec le spip_loader
[lhc/web/www.git] / www / ecrire / inc / filtres_dates.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2019 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Déclaration de filtres de dates pour les squelettes
15 *
16 * @package SPIP\Core\Filtres
17 **/
18 if (!defined('_ECRIRE_INC_VERSION')) {
19 return;
20 }
21
22
23 /**
24 * Extrait une date d'un texte et renvoie le résultat au format de date SQL
25 *
26 * L'année et le mois doivent être numériques.
27 * Le séparateur entre l'année et le mois peut être un `-`, un `:` ou un texte
28 * quelconque ne contenant pas de chiffres.
29 *
30 * Les jours ne sont pas pris en compte et le résultat est toujours le 1er du mois.
31 *
32 * @link http://www.spip.net/5516
33 * @param string $texte
34 * Texte contenant une date tel que `2008-04`
35 * @return string
36 * Date au format SQL tel que `2008-04-01`
37 **/
38 function extraire_date($texte) {
39 // format = 2001-08
40 if (preg_match(",([1-2][0-9]{3})[^0-9]*(1[0-2]|0?[1-9]),", $texte, $regs)) {
41 return $regs[1] . "-" . sprintf("%02d", $regs[2]) . "-01";
42 }
43 }
44
45
46 /**
47 * Normaliser une date vers le format datetime (Y-m-d H:i:s)
48 *
49 * @note
50 * Si elle vient du contexte (public/parametrer.php), on force le jour
51 *
52 * @filtre
53 * @link http://www.spip.net/5518
54 * @uses vider_date()
55 * @param string $date
56 * La date à normaliser
57 * @param bool $forcer_jour
58 * true pour forcer à indiquer un jour et mois (01) s'il n'y en a pas.
59 * @return string
60 * - une date au format datetime
61 * - une chaîne vide si la date est considérée nulle
62 **/
63 function normaliser_date($date, $forcer_jour = false) {
64 $date = vider_date($date);
65 if ($date) {
66 if (preg_match("/^[0-9]{8,10}$/", $date)) {
67 $date = date("Y-m-d H:i:s", $date);
68 }
69 if (preg_match("#^([12][0-9]{3})([-/]00)?( [-0-9:]+)?$#", $date, $regs)) {
70 $regs = array_pad($regs, 4, null); // eviter notice php
71 $date = $regs[1] . "-00-00" . $regs[3];
72 } else {
73 if (preg_match("#^([12][0-9]{3}[-/][01]?[0-9])([-/]00)?( [-0-9:]+)?$#", $date, $regs)) {
74 $regs = array_pad($regs, 4, null); // eviter notice php
75 $date = preg_replace("@/@", "-", $regs[1]) . "-00" . $regs[3];
76 } else {
77 $date = date("Y-m-d H:i:s", strtotime($date));
78 }
79 }
80
81 if ($forcer_jour) {
82 $date = str_replace('-00', '-01', $date);
83 }
84 }
85
86 return $date;
87 }
88
89 /**
90 * Enlève une date considérée comme vide
91 *
92 * @param string $letexte
93 * @return string
94 * - La date entrée (si elle n'est pas considérée comme nulle)
95 * - Une chaine vide
96 **/
97 function vider_date($letexte) {
98 if (strncmp("0000-00-00", $letexte, 10) == 0) {
99 return '';
100 }
101 if (strncmp("0001-01-01", $letexte, 10) == 0) {
102 return '';
103 }
104 if (strncmp("1970-01-01", $letexte, 10) == 0) {
105 return '';
106 } // eviter le bug GMT-1
107 return $letexte;
108 }
109
110 /**
111 * Retrouve à partir d'une chaîne les valeurs heures, minutes, secondes
112 *
113 * Retrouve une horaire au format `11:29:55`
114 *
115 * @param string $date
116 * Chaîne de date contenant éventuellement une horaire
117 * @return array
118 * - [heures, minutes, secondes] si horaire trouvée
119 * - [0, 0, 0] sinon
120 **/
121 function recup_heure($date) {
122
123 static $d = array(0, 0, 0);
124 if (!preg_match('#([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $date, $r)) {
125 return $d;
126 }
127
128 array_shift($r);
129
130 return $r;
131 }
132
133 /**
134 * Retourne l'heure d'une date
135 *
136 * @filtre
137 * @link http://www.spip.net/4293
138 * @uses recup_heure()
139 *
140 * @param string $numdate La date à extraire
141 * @return int heures, sinon 0
142 **/
143 function heures($numdate) {
144 $date_array = recup_heure($numdate);
145 if ($date_array) {
146 list($heures, $minutes, $secondes) = $date_array;
147 }
148
149 return $heures;
150 }
151
152 /**
153 * Retourne les minutes d'une date
154 *
155 * @filtre
156 * @link http://www.spip.net/4300
157 * @uses recup_heure()
158 *
159 * @param string $numdate La date à extraire
160 * @return int minutes, sinon 0
161 **/
162 function minutes($numdate) {
163 $date_array = recup_heure($numdate);
164 if ($date_array) {
165 list($heures, $minutes, $secondes) = $date_array;
166 }
167
168 return $minutes;
169 }
170
171 /**
172 * Retourne les secondes d'une date
173 *
174 * @filtre
175 * @link http://www.spip.net/4312
176 * @uses recup_heure()
177 *
178 * @param string $numdate La date à extraire
179 * @return int secondes, sinon 0
180 **/
181 function secondes($numdate) {
182 $date_array = recup_heure($numdate);
183 if ($date_array) {
184 list($heures, $minutes, $secondes) = $date_array;
185 }
186
187 return $secondes;
188 }
189
190 /**
191 * Retourne l'horaire (avec minutes) d'une date, tel que `12h36min`
192 *
193 * @note
194 * Le format de retour varie selon la langue utilisée.
195 *
196 * @filtre
197 * @link http://www.spip.net/5519
198 *
199 * @param string $numdate La date à extraire
200 * @return string L'heure formatée dans la langue en cours.
201 **/
202 function heures_minutes($numdate) {
203 return _T('date_fmt_heures_minutes', array('h' => heures($numdate), 'm' => minutes($numdate)));
204 }
205
206 /**
207 * Retrouve à partir d'une date les valeurs année, mois, jour, heures, minutes, secondes
208 *
209 * Annee, mois, jour sont retrouvés si la date contient par exemple :
210 * - '03/11/2015', '3/11/15'
211 * - '2015-11-04', '2015-11-4'
212 * - '2015-11'
213 *
214 * Dans ces cas, les heures, minutes, secondes sont retrouvés avec `recup_heure()`
215 *
216 * Annee, mois, jour, heures, minutes, secondes sont retrouvés si la date contient par exemple :
217 * - '20151104111420'
218 *
219 * @uses recup_heure()
220 *
221 * @param string $numdate La date à extraire
222 * @param bool $forcer_jour
223 * True pour tout le temps renseigner un jour ou un mois (le 1) s'il
224 * ne sont pas indiqués dans la date.
225 * @return array [année, mois, jour, heures, minutes, secondes]
226 **/
227 function recup_date($numdate, $forcer_jour = true) {
228 if (!$numdate) {
229 return '';
230 }
231 $heures = $minutes = $secondes = 0;
232 if (preg_match('#([0-9]{1,2})/([0-9]{1,2})/([0-9]{4}|[0-9]{1,2})#', $numdate, $regs)) {
233 $jour = $regs[1];
234 $mois = $regs[2];
235 $annee = $regs[3];
236 if ($annee < 90) {
237 $annee = 2000 + $annee;
238 } elseif ($annee < 100) {
239 $annee = 1900 + $annee;
240 }
241 list($heures, $minutes, $secondes) = recup_heure($numdate);
242
243 } elseif (preg_match('#([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})#', $numdate, $regs)) {
244 $annee = $regs[1];
245 $mois = $regs[2];
246 $jour = $regs[3];
247 list($heures, $minutes, $secondes) = recup_heure($numdate);
248 } elseif (preg_match('#([0-9]{4})-([0-9]{2})#', $numdate, $regs)) {
249 $annee = $regs[1];
250 $mois = $regs[2];
251 $jour = '';
252 list($heures, $minutes, $secondes) = recup_heure($numdate);
253 } elseif (preg_match('#^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$#', $numdate, $regs)) {
254 $annee = $regs[1];
255 $mois = $regs[2];
256 $jour = $regs[3];
257 $heures = $regs[4];
258 $minutes = $regs[5];
259 $secondes = $regs[6];
260 } else {
261 $annee = $mois = $jour = '';
262 }
263 if ($annee > 4000) {
264 $annee -= 9000;
265 }
266 if (strlen($jour) and substr($jour, 0, 1) == '0') {
267 $jour = substr($jour, 1);
268 }
269
270 if ($forcer_jour and $jour == '0') {
271 $jour = '1';
272 }
273 if ($forcer_jour and $mois == '0') {
274 $mois = '1';
275 }
276 if ($annee or $mois or $jour or $heures or $minutes or $secondes) {
277 return array($annee, $mois, $jour, $heures, $minutes, $secondes);
278 }
279 }
280
281 /**
282 * Retourne une date relative si elle est récente, sinon une date complète
283 *
284 * En fonction de la date transmise, peut retourner par exemple :
285 * - «il y a 3 minutes»,
286 * - «il y a 11 heures»,
287 * - «10 mai 2015 à 10h23min»
288 *
289 * @example `[(#DATE|date_interface)]`
290 *
291 * @filtre
292 * @link http://www.spip.net/5520
293 * @uses date_relative()
294 * @uses affdate_heure() utilisé si le décalage est trop grand
295 *
296 * @param string $date
297 * La date fournie
298 * @param int $decalage_maxi
299 * Durée écoulée, en secondes, à partir de laquelle on bascule sur une date complète.
300 * Par défaut +/- 12h.
301 * @return string
302 * La date relative ou complète
303 **/
304 function date_interface($date, $decalage_maxi = 43200 /* 12*3600 */) {
305 return sinon(
306 date_relative($date, $decalage_maxi),
307 affdate_heure($date)
308 );
309 }
310
311 /**
312 * Retourne une date relative (passée ou à venir)
313 *
314 * En fonction de la date transmise ainsi que de la date de référence
315 * (par défaut la date actuelle), peut retourner par exemple :
316 * - «il y a 3 minutes»,
317 * - «il y a 2 semmaines»,
318 * - «dans 1 semaine»
319 *
320 * @example
321 * - `[(#DATE|date_relative)]`
322 * - `[(#DATE|date_relative{43200})]`
323 * - `[(#DATE|date_relative{0, #AUTRE_DATE})]` Calcul relatif à une date spécifique
324 *
325 * @filtre
326 * @link http://www.spip.net/4277
327 *
328 * @param string $date
329 * La date fournie
330 * @param int $decalage_maxi
331 * Durée écoulée, en secondes, au delà de laquelle on ne retourne pas de date relative
332 * Indiquer `0` (par défaut) pour ignorer.
333 * @param string $ref_date
334 * La date de référence pour le calcul relatif, par défaut la date actuelle
335 * @return string
336 * - La date relative
337 * - "" si un dépasse le décalage maximum est indiqué et dépassé.
338 **/
339 function date_relative($date, $decalage_maxi = 0, $ref_date = null) {
340
341 if (is_null($ref_date)) {
342 $ref_time = time();
343 } else {
344 $ref_time = strtotime($ref_date);
345 }
346
347 if (!$date) {
348 return;
349 }
350 $decal = date("U", $ref_time) - date("U", strtotime($date));
351
352 if ($decalage_maxi and ($decal > $decalage_maxi or $decal < 0)) {
353 return '';
354 }
355
356 if ($decal < 0) {
357 $il_y_a = "date_dans";
358 $decal = -1 * $decal;
359 } else {
360 $il_y_a = "date_il_y_a";
361 }
362
363 if ($decal > 3600 * 24 * 30 * 6) {
364 return affdate_court($date);
365 }
366
367 if ($decal > 3600 * 24 * 30) {
368 $mois = floor($decal / (3600 * 24 * 30));
369 if ($mois < 2) {
370 $delai = "$mois " . _T("date_un_mois");
371 } else {
372 $delai = "$mois " . _T("date_mois");
373 }
374 } else {
375 if ($decal > 3600 * 24 * 7) {
376 $semaines = floor($decal / (3600 * 24 * 7));
377 if ($semaines < 2) {
378 $delai = "$semaines " . _T("date_une_semaine");
379 } else {
380 $delai = "$semaines " . _T("date_semaines");
381 }
382 } else {
383 if ($decal > 3600 * 24) {
384 $jours = floor($decal / (3600 * 24));
385 if ($jours < 2) {
386 return $il_y_a == "date_dans" ? _T("date_demain") : _T("date_hier");
387 } else {
388 $delai = "$jours " . _T("date_jours");
389 }
390 } else {
391 if ($decal >= 3600) {
392 $heures = floor($decal / 3600);
393 if ($heures < 2) {
394 $delai = "$heures " . _T("date_une_heure");
395 } else {
396 $delai = "$heures " . _T("date_heures");
397 }
398 } else {
399 if ($decal >= 60) {
400 $minutes = floor($decal / 60);
401 if ($minutes < 2) {
402 $delai = "$minutes " . _T("date_une_minute");
403 } else {
404 $delai = "$minutes " . _T("date_minutes");
405 }
406 } else {
407 $secondes = ceil($decal);
408 if ($secondes < 2) {
409 $delai = "$secondes " . _T("date_une_seconde");
410 } else {
411 $delai = "$secondes " . _T("date_secondes");
412 }
413 }
414 }
415 }
416 }
417 }
418
419 return _T($il_y_a, array("delai" => $delai));
420 }
421
422
423 /**
424 * Retourne une date relative courte (passée ou à venir)
425 *
426 * Retourne «hier», «aujourd'hui» ou «demain» si la date correspond, sinon
427 * utilise `date_relative()`
428 *
429 * @example `[(#DATE|date_relativecourt)]`
430 *
431 * @filtre
432 * @uses date_relative()
433 *
434 * @param string $date
435 * La date fournie
436 * @param int $decalage_maxi
437 * Durée écoulée, en secondes, au delà de laquelle on ne retourne pas de date relative
438 * Indiquer `0` (par défaut) pour ignorer.
439 * @return string
440 * - La date relative
441 * - "" si un dépasse le décalage maximum est indiqué et dépassé.
442 **/
443 function date_relativecourt($date, $decalage_maxi = 0) {
444
445 if (!$date) {
446 return;
447 }
448 $decal = date("U", strtotime(date('Y-m-d')) - strtotime(date('Y-m-d', strtotime($date))));
449
450 if ($decalage_maxi and ($decal > $decalage_maxi or $decal < 0)) {
451 return '';
452 }
453
454 if ($decal < -24 * 3600) {
455 $retour = date_relative($date, $decalage_maxi);
456 } elseif ($decal < 0) {
457 $retour = _T("date_demain");
458 } else {
459 if ($decal < (3600 * 24)) {
460 $retour = _T("date_aujourdhui");
461 } else {
462 if ($decal < (3600 * 24 * 2)) {
463 $retour = _T("date_hier");
464 } else {
465 $retour = date_relative($date, $decalage_maxi);
466 }
467 }
468 }
469
470 return $retour;
471 }
472
473 /**
474 * Formatage humain de la date `$numdate` selon le format `$vue`
475 *
476 * @param string $numdate
477 * Une écriture de date
478 * @param string $vue
479 * Type de format souhaité ou expression pour `strtotime()` tel que `Y-m-d h:i:s`
480 * @param array $options {
481 * @type string $param
482 * 'abbr' ou 'initiale' permet d'afficher les jours au format court ou initiale
483 * @type int $annee_courante
484 * Permet de definir l'annee de reference pour l'affichage des dates courtes
485 * }
486 * @return mixed|string
487 */
488 function affdate_base($numdate, $vue, $options = array()) {
489 if (is_string($options)) {
490 $options = array('param' => $options);
491 }
492 $date_array = recup_date($numdate, false);
493 if (!$date_array) {
494 return;
495 }
496 list($annee, $mois, $jour, $heures, $minutes, $secondes) = $date_array;
497
498 // 1er, 21st, etc.
499 $journum = $jour;
500
501 if ($jour == 0) {
502 $jour = '';
503 $njour = 0;
504 } else {
505 $njour = intval($jour);
506 if ($jourth = _T('date_jnum' . $jour)) {
507 $jour = $jourth;
508 }
509 }
510
511 $mois = intval($mois);
512 if ($mois > 0 and $mois < 13) {
513 $nommois = _T('date_mois_' . $mois);
514 if ($jour) {
515 $jourmois = _T('date_de_mois_' . $mois, array('j' => $jour, 'nommois' => $nommois));
516 } else {
517 $jourmois = $nommois;
518 }
519 } else {
520 $nommois = '';
521 $jourmois = '';
522 }
523
524 if ($annee < 0) {
525 $annee = -$annee . " " . _T('date_avant_jc');
526 $avjc = true;
527 } else {
528 $avjc = false;
529 }
530
531 switch ($vue) {
532 case 'saison':
533 case 'saison_annee':
534 $saison = '';
535 if ($mois > 0) {
536 $saison = ($options['param'] == 'sud') ? 3 : 1;
537 if (($mois == 3 and $jour >= 21) or $mois > 3) {
538 $saison = ($options['param'] == 'sud') ? 4 : 2;
539 }
540 if (($mois == 6 and $jour >= 21) or $mois > 6) {
541 $saison = ($options['param'] == 'sud') ? 1 : 3;
542 }
543 if (($mois == 9 and $jour >= 21) or $mois > 9) {
544 $saison = ($options['param'] == 'sud') ? 2 : 4;
545 }
546 if (($mois == 12 and $jour >= 21) or $mois > 12) {
547 $saison = ($options['param'] == 'sud') ? 3 : 1;
548 }
549 }
550 if ($vue == 'saison') {
551 return $saison ? _T('date_saison_' . $saison) : '';
552 } else {
553 return $saison ? trim(_T('date_fmt_saison_annee',
554 array('saison' => _T('date_saison_' . $saison), 'annee' => $annee))) : '';
555 }
556
557 case 'court':
558 if ($avjc) {
559 return $annee;
560 }
561 $a = ((isset($options['annee_courante']) and $options['annee_courante']) ? $options['annee_courante'] : date('Y'));
562 if ($annee < ($a - 100) or $annee > ($a + 100)) {
563 return $annee;
564 }
565 if ($annee != $a) {
566 return _T('date_fmt_mois_annee',
567 array('mois' => $mois, 'nommois' => spip_ucfirst($nommois), 'annee' => $annee));
568 }
569
570 return _T('date_fmt_jour_mois',
571 array('jourmois' => $jourmois, 'jour' => $jour, 'mois' => $mois, 'nommois' => $nommois, 'annee' => $annee));
572
573 case 'jourcourt':
574 if ($avjc) {
575 return $annee;
576 }
577 $a = ((isset($options['annee_courante']) and $options['annee_courante']) ? $options['annee_courante'] : date('Y'));
578 if ($annee < ($a - 100) or $annee > ($a + 100)) {
579 return $annee;
580 }
581 if ($annee != $a) {
582 return _T('date_fmt_jour_mois_annee',
583 array('jourmois' => $jourmois, 'jour' => $jour, 'mois' => $mois, 'nommois' => $nommois, 'annee' => $annee));
584 }
585
586 return _T('date_fmt_jour_mois',
587 array('jourmois' => $jourmois, 'jour' => $jour, 'mois' => $mois, 'nommois' => $nommois, 'annee' => $annee));
588
589 case 'entier':
590 if ($avjc) {
591 return $annee;
592 }
593 if ($jour) {
594 return _T('date_fmt_jour_mois_annee',
595 array('jourmois' => $jourmois, 'jour' => $jour, 'mois' => $mois, 'nommois' => $nommois, 'annee' => $annee));
596 } elseif ($mois) {
597 return trim(_T('date_fmt_mois_annee', array('mois' => $mois, 'nommois' => $nommois, 'annee' => $annee)));
598 } else {
599 return $annee;
600 }
601
602 case 'nom_mois':
603 $param = ((isset($options['param']) and $options['param']) ? '_' . $options['param'] : '');
604 if ($param and $mois) {
605 return _T('date_mois_' . $mois . $param);
606 }
607
608 return $nommois;
609
610 case 'mois':
611 return sprintf("%02s", $mois);
612
613 case 'jour':
614 return $jour;
615
616 case 'journum':
617 return $journum;
618
619 case 'nom_jour':
620 if (!$mois or !$njour) {
621 return '';
622 }
623 $nom = mktime(1, 1, 1, $mois, $njour, $annee);
624 $nom = 1 + date('w', $nom);
625 $param = ((isset($options['param']) and $options['param']) ? '_' . $options['param'] : '');
626
627 return _T('date_jour_' . $nom . $param);
628
629 case 'mois_annee':
630 if ($avjc) {
631 return $annee;
632 }
633
634 return trim(_T('date_fmt_mois_annee', array('mois' => $mois, 'nommois' => $nommois, 'annee' => $annee)));
635
636 case 'annee':
637 return $annee;
638
639 // Cas d'une vue non definie : retomber sur le format
640 // de date propose par http://www.php.net/date
641 default:
642 list($annee, $mois, $jour, $heures, $minutes, $secondes) = $date_array;
643 if (!$time = mktime($heures, $minutes, $secondes, $mois, $jour, $annee)) {
644 $time = strtotime($numdate);
645 }
646 return date($vue, $time);
647 }
648 }
649
650
651 /**
652 * Affiche le nom du jour pour une date donnée
653 *
654 * @example
655 * - `[(#DATE|nom_jour)]` lundi
656 * - `[(#DATE|nom_jour{abbr})]` lun.
657 * - `[(#DATE|nom_jour{initiale})]` l.
658 *
659 * @filtre
660 * @link http://www.spip.net/4305
661 * @uses affdate_base()
662 *
663 * @param string $numdate
664 * Une écriture de date
665 * @param string $forme
666 * Forme spécifique de retour :
667 * - initiale : l'initiale du jour
668 * - abbr : abbréviation du jour
669 * - '' : le nom complet (par défaut)
670 * @return string
671 * Nom du jour
672 **/
673 function nom_jour($numdate, $forme = '') {
674 if (!($forme == 'abbr' or $forme == 'initiale')) {
675 $forme = '';
676 }
677
678 return affdate_base($numdate, 'nom_jour', $forme);
679 }
680
681 /**
682 * Affiche le numéro du jour (1er à 31) pour une date donnée
683 *
684 * Utilise une abbréviation (exemple "1er") pour certains jours,
685 * en fonction de la langue utilisée.
686 *
687 * @example `[(#DATE|jour)]`
688 *
689 * @filtre
690 * @link http://www.spip.net/4295
691 * @uses affdate_base()
692 * @see journum()
693 *
694 * @param string $numdate
695 * Une écriture de date
696 * @return int
697 * Numéro du jour
698 **/
699 function jour($numdate) {
700 return affdate_base($numdate, 'jour');
701 }
702
703 /**
704 * Affiche le numéro du jour (1 à 31) pour une date donnée
705 *
706 * @example `[(#DATE|journum)]`
707 *
708 * @filtre
709 * @uses affdate_base()
710 * @see jour()
711 *
712 * @param string $numdate
713 * Une écriture de date
714 * @return int
715 * Numéro du jour
716 **/
717 function journum($numdate) {
718 return affdate_base($numdate, 'journum');
719 }
720
721 /**
722 * Affiche le numéro du mois (01 à 12) pour une date donnée
723 *
724 * @example `[(#DATE|mois)]`
725 *
726 * @filtre
727 * @link http://www.spip.net/4303
728 * @uses affdate_base()
729 *
730 * @param string $numdate
731 * Une écriture de date
732 * @return string
733 * Numéro du mois (sur 2 chiffres)
734 **/
735 function mois($numdate) {
736 return affdate_base($numdate, 'mois');
737 }
738
739 /**
740 * Affiche le nom du mois pour une date donnée
741 *
742 * @example
743 * - `[(#DATE|nom_mois)]` novembre
744 * - `[(#DATE|nom_mois{abbr})]` nov.
745 *
746 * @filtre
747 * @link http://www.spip.net/4306
748 * @uses affdate_base()
749 *
750 * @param string $numdate
751 * Une écriture de date
752 * @param string $forme
753 * Forme spécifique de retour :
754 * - abbr : abbréviation du mois
755 * - '' : le nom complet (par défaut)
756 * @return string
757 * Nom du mois
758 **/
759 function nom_mois($numdate, $forme = '') {
760 if (!($forme == 'abbr')) {
761 $forme = '';
762 }
763
764 return affdate_base($numdate, 'nom_mois', $forme);
765 }
766
767 /**
768 * Affiche l'année sur 4 chiffres d'une date donnée
769 *
770 * @example `[(#DATE|annee)]`
771 *
772 * @filtre
773 * @link http://www.spip.net/4146
774 * @uses affdate_base()
775 *
776 * @param string $numdate
777 * Une écriture de date
778 * @return int
779 * Année (sur 4 chiffres)
780 **/
781 function annee($numdate) {
782 return affdate_base($numdate, 'annee');
783 }
784
785
786 /**
787 * Affiche le nom boréal ou austral de la saison
788 *
789 * @filtre
790 * @link http://www.spip.net/4311
791 * @uses affdate_base()
792 * @example
793 * En PHP
794 * ```
795 * saison("2008-10-11 14:08:45") affiche "automne"
796 * saison("2008-10-11 14:08:45", "sud") affiche "printemps"
797 * ```
798 * En squelettes
799 * ```
800 * [(#DATE|saison)]
801 * [(#DATE|saison{sud})]
802 * ```
803 *
804 * @param string $numdate
805 * Une écriture de date
806 * @param string $hemisphere
807 * Nom optionnel de l'hémisphère (sud ou nord) ; par défaut nord
808 * @return string
809 * La date formatée
810 **/
811 function saison($numdate, $hemisphere = 'nord') {
812 if ($hemisphere != 'sud') {
813 $hemisphere = 'nord';
814 }
815
816 return affdate_base($numdate, 'saison', $hemisphere);
817 }
818
819
820 /**
821 * Affiche le nom boréal ou austral de la saison suivi de l'année en cours
822 *
823 * @filtre
824 * @uses affdate_base()
825 * @example
826 * En PHP
827 * ```
828 * saison_annee("2008-10-11 14:08:45") affiche "automne 2008"
829 * saison_annee("2008-10-11 14:08:45", "sud") affiche "printemps 2008"
830 * ```
831 * En squelettes
832 * ```
833 * [(#DATE|saison_annee)]
834 * [(#DATE|saison_annee{sud})]
835 * ```
836 *
837 * @param string $numdate
838 * Une écriture de date
839 * @param string $hemisphere
840 * Nom optionnel de l'hémisphère (sud ou nord) ; par défaut nord
841 * @return string
842 * La date formatée
843 **/
844 function saison_annee($numdate, $hemisphere = 'nord') {
845 if ($hemisphere != 'sud') {
846 $hemisphere = 'nord';
847 }
848
849 return affdate_base($numdate, 'saison_annee', $hemisphere);
850 }
851
852 /**
853 * Formate une date
854 *
855 * @example
856 * En PHP`affdate("2008-10-11 14:08:45")` affiche "11 octobre 2008"
857 *
858 * @example
859 * En squelettes
860 * - `[(#DATE|affdate)]`
861 * - `[(#DATE|affdate{Y-m-d})]`
862 *
863 * @filtre
864 * @link http://www.spip.net/4129
865 * @uses affdate_base()
866 * @see affdate_court()
867 * @see affdate_jourcourt()
868 *
869 * @param string $numdate
870 * Une écriture de date
871 * @param string $format
872 * Type de format souhaité ou expression pour `strtotime()` tel que `Y-m-d h:i:s`
873 * @return string
874 * La date formatée
875 **/
876 function affdate($numdate, $format = 'entier') {
877 return affdate_base($numdate, $format);
878 }
879
880
881 /**
882 * Formate une date, omet l'année si année courante, sinon omet le jour
883 *
884 * Si l'année actuelle (ou indiquée dans `$annee_courante`) est 2015,
885 * retournera "21 juin" si la date en entrée est le 21 juin 2015,
886 * mais retournera "juin 2013" si la date en entrée est le 21 juin 2013.
887 *
888 * @example `[(#DATE|affdate_court)]`
889 *
890 * @filtre
891 * @link http://www.spip.net/4130
892 * @uses affdate_base()
893 * @see affdate()
894 * @see affdate_jourcourt()
895 *
896 * @param string $numdate
897 * Une écriture de date
898 * @param int|null $annee_courante
899 * L'année de comparaison, utilisera l'année en cours si omis.
900 * @return string
901 * La date formatée
902 **/
903 function affdate_court($numdate, $annee_courante = null) {
904 return affdate_base($numdate, 'court', array('annee_courante' => $annee_courante));
905 }
906
907
908 /**
909 * Formate une date, omet l'année si année courante
910 *
911 * Si l'année actuelle (ou indiquée dans `$annee_courante`) est 2015,
912 * retournera "21 juin" si la date en entrée est le 21 juin 2015,
913 * mais retournera "21 juin 2013" si la date en entrée est le 21 juin 2013.
914 *
915 * @example `[(#DATE|affdate_jourcourt)]`
916 *
917 * @filtre
918 * @link http://www.spip.net/4131
919 * @uses affdate_base()
920 * @see affdate()
921 * @see affdate_court()
922 *
923 * @param string $numdate
924 * Une écriture de date
925 * @param int|null $annee_courante
926 * L'année de comparaison, utilisera l'année en cours si omis.
927 * @return string
928 * La date formatée
929 **/
930 function affdate_jourcourt($numdate, $annee_courante = null) {
931 return affdate_base($numdate, 'jourcourt', array('annee_courante' => $annee_courante));
932 }
933
934 /**
935 * Retourne le mois en toute lettre et l’année d'une date
936 *
937 * Ne retourne pas le jour donc.
938 *
939 * @filtre
940 * @link http://www.spip.net/4132
941 * @uses affdate_base()
942 *
943 * @param string $numdate
944 * Une écriture de date
945 * @return string
946 * La date formatée
947 **/
948 function affdate_mois_annee($numdate) {
949 return affdate_base($numdate, 'mois_annee');
950 }
951
952 /**
953 * Retourne la date suivie de l'heure
954 *
955 * @example `[(#DATE|affdate_heure)]` peut donner "11 novembre 2015 à 11h10min"
956 *
957 * @filtre
958 * @uses recup_date()
959 * @uses affdate()
960 *
961 * @param string $numdate
962 * Une écriture de date
963 * @return string
964 * La date formatée
965 **/
966 function affdate_heure($numdate) {
967 $date_array = recup_date($numdate);
968 if (!$date_array) {
969 return;
970 }
971 list($annee, $mois, $jour, $heures, $minutes, $sec) = $date_array;
972
973 return _T('date_fmt_jour_heure', array(
974 'jour' => affdate($numdate),
975 'heure' => _T('date_fmt_heures_minutes', array('h' => $heures, 'm' => $minutes))
976 ));
977 }
978
979 /**
980 * Afficher de facon textuelle les dates de début et fin en fonction des cas
981 *
982 * - Lundi 20 fevrier a 18h
983 * - Le 20 fevrier de 18h a 20h
984 * - Du 20 au 23 fevrier
985 * - Du 20 fevrier au 30 mars
986 * - Du 20 fevrier 2007 au 30 mars 2008
987 *
988 * `$horaire='oui'` ou `true` permet d'afficher l'horaire,
989 * toute autre valeur n'indique que le jour
990 * `$forme` peut contenir une ou plusieurs valeurs parmi
991 * - `abbr` (afficher le nom des jours en abrege)
992 * - `hcal` (generer une date au format hcal)
993 * - `jour` (forcer l'affichage des jours)
994 * - `annee` (forcer l'affichage de l'annee)
995 *
996 * @param string $date_debut
997 * @param string $date_fin
998 * @param string $horaire
999 * @param string $forme
1000 * - `abbr` pour afficher le nom du jour en abrege (Dim. au lieu de Dimanche)
1001 * - `annee` pour forcer l'affichage de l'annee courante
1002 * - `jour` pour forcer l'affichage du nom du jour
1003 * - `hcal` pour avoir un markup microformat abbr
1004 * @return string
1005 * Texte de la date
1006 */
1007 function affdate_debut_fin($date_debut, $date_fin, $horaire = 'oui', $forme = '') {
1008 $abbr = $jour = '';
1009 $affdate = "affdate_jourcourt";
1010 if (strpos($forme, 'abbr') !== false) {
1011 $abbr = 'abbr';
1012 }
1013 if (strpos($forme, 'annee') !== false) {
1014 $affdate = 'affdate';
1015 }
1016 if (strpos($forme, 'jour') !== false) {
1017 $jour = 'jour';
1018 }
1019
1020 $dtstart = $dtend = $dtabbr = "";
1021 if (strpos($forme, 'hcal') !== false) {
1022 $dtstart = "<abbr class='dtstart' title='" . date_iso($date_debut) . "'>";
1023 $dtend = "<abbr class='dtend' title='" . date_iso($date_fin) . "'>";
1024 $dtabbr = "</abbr>";
1025 }
1026
1027 $date_debut = strtotime($date_debut);
1028 $date_fin = strtotime($date_fin);
1029 $d = date("Y-m-d", $date_debut);
1030 $f = date("Y-m-d", $date_fin);
1031 $h = ($horaire === 'oui' or $horaire === true);
1032 $hd = _T('date_fmt_heures_minutes_court', array('h' => date("H", $date_debut), 'm' => date("i", $date_debut)));
1033 $hf = _T('date_fmt_heures_minutes_court', array('h' => date("H", $date_fin), 'm' => date("i", $date_fin)));
1034
1035 if ($d == $f) { // meme jour
1036 $nomjour = nom_jour($d, $abbr);
1037 $s = $affdate($d);
1038 $s = _T('date_fmt_jour', array('nomjour' => $nomjour, 'jour' => $s));
1039 if ($h) {
1040 if ($hd == $hf) {
1041 // Lundi 20 fevrier a 18h25
1042 $s = spip_ucfirst(_T('date_fmt_jour_heure', array('jour' => $s, 'heure' => $hd)));
1043 $s = "$dtstart$s$dtabbr";
1044 } else {
1045 // Le <abbr...>lundi 20 fevrier de 18h00</abbr> a <abbr...>20h00</abbr>
1046 if ($dtabbr && $dtstart && $dtend) {
1047 $s = _T('date_fmt_jour_heure_debut_fin_abbr', array(
1048 'jour' => spip_ucfirst($s),
1049 'heure_debut' => $hd,
1050 'heure_fin' => $hf,
1051 'dtstart' => $dtstart,
1052 'dtend' => $dtend,
1053 'dtabbr' => $dtabbr
1054 ),
1055 array(
1056 'sanitize' => false
1057 )
1058 );
1059 } // Le lundi 20 fevrier de 18h00 a 20h00
1060 else {
1061 $s = spip_ucfirst(_T('date_fmt_jour_heure_debut_fin',
1062 array('jour' => $s, 'heure_debut' => $hd, 'heure_fin' => $hf)));
1063 }
1064 }
1065 } else {
1066 if ($dtabbr && $dtstart) {
1067 $s = $dtstart . spip_ucfirst($s) . $dtabbr;
1068 } else {
1069 $s = spip_ucfirst($s);
1070 }
1071 }
1072 } else {
1073 if ((date("Y-m", $date_debut)) == date("Y-m", $date_fin)) { // meme annee et mois, jours differents
1074 if (!$h) {
1075 $date_debut = jour($d);
1076 } else {
1077 $date_debut = affdate_jourcourt($d, date("Y", $date_fin));
1078 }
1079 $date_fin = $affdate($f);
1080 if ($jour) {
1081 $nomjour_debut = nom_jour($d, $abbr);
1082 $date_debut = _T('date_fmt_jour', array('nomjour' => $nomjour_debut, 'jour' => $date_debut));
1083 $nomjour_fin = nom_jour($f, $abbr);
1084 $date_fin = _T('date_fmt_jour', array('nomjour' => $nomjour_fin, 'jour' => $date_fin));
1085 }
1086 if ($h) {
1087 $date_debut = _T('date_fmt_jour_heure', array('jour' => $date_debut, 'heure' => $hd));
1088 $date_fin = _T('date_fmt_jour_heure', array('jour' => $date_fin, 'heure' => $hf));
1089 }
1090 $date_debut = $dtstart . $date_debut . $dtabbr;
1091 $date_fin = $dtend . $date_fin . $dtabbr;
1092
1093 $s = _T('date_fmt_periode', array('date_debut' => $date_debut, 'date_fin' => $date_fin));
1094 } else {
1095 $date_debut = affdate_jourcourt($d, date("Y", $date_fin));
1096 $date_fin = $affdate($f);
1097 if ($jour) {
1098 $nomjour_debut = nom_jour($d, $abbr);
1099 $date_debut = _T('date_fmt_jour', array('nomjour' => $nomjour_debut, 'jour' => $date_debut));
1100 $nomjour_fin = nom_jour($f, $abbr);
1101 $date_fin = _T('date_fmt_jour', array('nomjour' => $nomjour_fin, 'jour' => $date_fin));
1102 }
1103 if ($h) {
1104 $date_debut = _T('date_fmt_jour_heure', array('jour' => $date_debut, 'heure' => $hd));
1105 $date_fin = _T('date_fmt_jour_heure', array('jour' => $date_fin, 'heure' => $hf));
1106 }
1107
1108 $date_debut = $dtstart . $date_debut . $dtabbr;
1109 $date_fin = $dtend . $date_fin . $dtabbr;
1110 $s = _T('date_fmt_periode', array('date_debut' => $date_debut, 'date_fin' => $date_fin));
1111
1112 }
1113 }
1114
1115 return $s;
1116 }
1117
1118 /**
1119 * Adapte une date pour être insérée dans une valeur de date d'un export ICAL
1120 *
1121 * Retourne une date au format `Ymd\THis\Z`, tel que '20150428T163254Z'
1122 *
1123 * @example `DTSTAMP:[(#DATE|date_ical)]`
1124 * @filtre
1125 * @uses recup_heure()
1126 * @uses recup_date()
1127 *
1128 * @param string $date
1129 * La date
1130 * @param int $addminutes
1131 * Ajouter autant de minutes à la date
1132 * @return string
1133 * Date au format ical
1134 **/
1135 function date_ical($date, $addminutes = 0) {
1136 list($heures, $minutes, $secondes) = recup_heure($date);
1137 list($annee, $mois, $jour) = recup_date($date);
1138
1139 return gmdate("Ymd\THis\Z", mktime($heures, $minutes + $addminutes, $secondes, $mois, $jour, $annee));
1140 }
1141
1142
1143 /**
1144 * Retourne une date formattée au format "RFC 3339" ou "ISO 8601"
1145 *
1146 * @example `[(#DATE|date_iso)]` peut donner "2015-11-11T10:13:45Z"
1147 *
1148 * @filtre
1149 * @link http://www.spip.net/5641
1150 * @link https://fr.wikipedia.org/wiki/ISO_8601
1151 * @link http://www.ietf.org/rfc/rfc3339.txt
1152 * @link http://php.net/manual/fr/class.datetime.php
1153 *
1154 * @uses recup_date()
1155 * @uses recup_heure()
1156 *
1157 * @param string $date_heure
1158 * Une écriture de date
1159 * @return string
1160 * La date formatée
1161 **/
1162 function date_iso($date_heure) {
1163 list($annee, $mois, $jour) = recup_date($date_heure);
1164 list($heures, $minutes, $secondes) = recup_heure($date_heure);
1165 $time = @mktime($heures, $minutes, $secondes, $mois, $jour, $annee);
1166
1167 return gmdate('Y-m-d\TH:i:s\Z', $time);
1168 }
1169
1170 /**
1171 * Retourne une date formattée au format "RFC 822"
1172 *
1173 * Utilisé pour `<pubdate>` dans certains flux RSS
1174 *
1175 * @example `[(#DATE|date_822)]` peut donner "Wed, 11 Nov 2015 11:13:45 +0100"
1176 *
1177 * @filtre
1178 * @link http://www.spip.net/4276
1179 * @link http://php.net/manual/fr/class.datetime.php
1180 *
1181 * @uses recup_date()
1182 * @uses recup_heure()
1183 *
1184 * @param string $date_heure
1185 * Une écriture de date
1186 * @return string
1187 * La date formatée
1188 **/
1189 function date_822($date_heure) {
1190 list($annee, $mois, $jour) = recup_date($date_heure);
1191 list($heures, $minutes, $secondes) = recup_heure($date_heure);
1192 $time = mktime($heures, $minutes, $secondes, $mois, $jour, $annee);
1193
1194 return date('r', $time);
1195 }
1196
1197 /**
1198 * Pour une date commençant par `Y-m-d`, retourne `Ymd`
1199 *
1200 * @example `date_anneemoisjour('2015-10-11 11:27:03')` retourne `20151011`
1201 * @see date_anneemois()
1202 *
1203 * @param string $d
1204 * Une écriture de date commençant par un format `Y-m-d` (comme date ou datetime SQL).
1205 * Si vide, utilise la date actuelle.
1206 * @return string
1207 * Date au format `Ymd`
1208 **/
1209 function date_anneemoisjour($d) {
1210 if (!$d) {
1211 $d = date("Y-m-d");
1212 }
1213
1214 return substr($d, 0, 4) . substr($d, 5, 2) . substr($d, 8, 2);
1215 }
1216
1217 /**
1218 * Pour une date commençant par `Y-m`, retourne `Ym`
1219 *
1220 * @example `date_anneemoisjour('2015-10-11 11:27:03')` retourne `201510`
1221 * @see date_anneemoisjour()
1222 *
1223 * @param string $d
1224 * Une écriture de date commençant par un format `Y-m` (comme date ou datetime SQL).
1225 * Si vide, utilise la date actuelle.
1226 * @return string
1227 * Date au format `Ym`
1228 **/
1229 function date_anneemois($d) {
1230 if (!$d) {
1231 $d = date("Y-m-d");
1232 }
1233
1234 return substr($d, 0, 4) . substr($d, 5, 2);
1235 }
1236
1237 /**
1238 * Retourne le premier jour (lundi) de la même semaine au format `Ymd`
1239 *
1240 * @example `date_debut_semaine(2015, 11, 11)` retourne `20151109`
1241 * @see date_fin_semaine()
1242 *
1243 * @param int $annee
1244 * @param int $mois
1245 * @param int $jour
1246 * @return string
1247 * Date au lundi de la même semaine au format `Ymd`
1248 **/
1249 function date_debut_semaine($annee, $mois, $jour) {
1250 $w_day = date("w", mktime(0, 0, 0, $mois, $jour, $annee));
1251 if ($w_day == 0) {
1252 $w_day = 7;
1253 } // Gaffe: le dimanche est zero
1254 $debut = $jour - $w_day + 1;
1255
1256 return date("Ymd", mktime(0, 0, 0, $mois, $debut, $annee));
1257 }
1258
1259 /**
1260 * Retourne le dernier jour (dimanche) de la même semaine au format `Ymd`
1261 *
1262 * @example `date_debut_semaine(2015, 11, 11)` retourne `20151115`
1263 * @see date_fin_semaine()
1264 *
1265 * @param int $annee
1266 * @param int $mois
1267 * @param int $jour
1268 * @return string
1269 * Date au dimanche de la même semaine au format `Ymd`
1270 **/
1271 function date_fin_semaine($annee, $mois, $jour) {
1272 $w_day = date("w", mktime(0, 0, 0, $mois, $jour, $annee));
1273 if ($w_day == 0) {
1274 $w_day = 7;
1275 } // Gaffe: le dimanche est zero
1276 $debut = $jour - $w_day + 1;
1277
1278 return date("Ymd", mktime(0, 0, 0, $mois, $debut + 6, $annee));
1279 }
1280