Dépôt officiel du core SPIP * Copie possible par svn sur svn://trac.rezo.net/spip * Les svn:externals sont présent dans https://git.spip.net/SPIP/[nom du plugin dist] https://www.spip.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1281 lines
34 KiB

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