Année inférieure à 1970 et supérieure à 2036
FerméPierrotLeFou - 11 mars 2023 à 06:50
- Année inférieure à 1970 et supérieure à 2036
- Info free: votre encours sur le service internet est supérieur à 10 €. ✓ - Forum iPhone
- Cette photo n’a pas été prise cette année. trouvez la date, l'heure et avec quel modèle d'appareil photo elle a été prise. - Forum Samsung
- 20 janvier 1970 whatsapp ✓ - Forum iPhone
8 réponses
8 mars 2023 à 14:38
bonjour,
"il plante", ?
Je ne connais rien à PHP mais ça me suggère que les dates sont enregistrées dans le format de Unix qui commence au 1 janvier 1970 à minuit.
Et le registre serait saturé (32 bits?) justement en 2036.
Il faut garder les dates en clair et les traiter soi-même.
9 mars 2023 à 07:39
Il faut probablement adapter le code PHP.
9 mars 2023 à 07:42
Merci, mais cela ne m'avance guère, avant de poser cette question, j'avais déjà fait un peu le tour sur internet, sans réponse satisfaisante.
9 mars 2023 à 07:47
Comment pouvons-nous être plus précis sans que tu ne partages ton code?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question9 mars 2023 à 11:24
Voilà tout mon code :
1 - index.php
<?php namespace App; require_once __DIR__ . '/vendor/autoload.php'; $url = $_SERVER['PHP_SELF']; $year = new Year($_GET['year'] ?? null); ?> <!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Calendrier</title> <!-- Favicon --> <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> <!-- Styles CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css"> <link rel="stylesheet" href="css/calend.css"> <!-- Scripts --> <script src="js/date.prototype.js" defer></script> <script src="js/date.time.js" defer></script> <script src="js/calend.js" defer></script> </head> <body> <div class="container"> <header> <div class="datetime"> <span class="date"></span><br> <span class="num-day"></span> <span class="num-week"></span><br> <span class="reste"></span> </div> <h1><a href="/">Calendrier <?= $year->year ?></a></h1> <div class="time"></div> </header> <nav> <a href="/?year=<?= $year->prevYear()->year ?>" class="btn btn-primary"><i class="fa-sharp fa-solid fa-backward"></i></a> <button class="btn btn-success" id="premier">Premier semestre</button> <button class="btn btn-success" id="second">Deuxième semestre</button> <button class="btn btn-success" id="feries">Jours fériés</button> <a href="/?year=<?= $year->nextYear()->year ?>" class="btn btn-primary"><i class="fa-sharp fa-solid fa-forward"></i></a> </nav> <section id="sect01"> <?= $year->getFirstSem($year->year) ?> </section> <section id="sect02"> <?= $year->getSecondSem($year->year) ?> </section> <section id="sect03"> <div class="content"> <div class="top-header"> <p>Jours fériés <?= $year->year ?></p> </div> <div class="ferie_det"> <div class="detail"> <p>Jour de l'an</p> <p><?= $year->oneJan($year->year) ?> 1er janvier</p> </div> <div class="detail"> <p>Lundi de pâques</p> <p>Lundi <?= $year->paques($year->year) ?></p> </div> <div class="detail"> <p>Fête du travail</p> <p><?= $year->travail($year->year) ?> 1er mai</p> </div> <div class="detail"> <p>Victoire 1945</p> <p><?= $year->victoire($year->year) ?> 8 mai</p> </div> <div class="detail"> <p>Ascension</p> <p> Jeudi <?= $year->ascension($year->year) ?></p> </div> <div class="detail"> <p>Lundi de pentecôte</p> <p>Lundi <?= $year->pentecote($year->year) ?></p> </div> <div class="detail"> <p>Fête nationale</p> <p>Vendredi 14 juillet</p> </div> <div class="detail"> <p>Assomption</p> <p><?= $year->assomption($year->year) ?> 15 août</p> </div> <div class="detail"> <p>Toussaint</p> <p><?= $year->toussaint($year->year) ?> 1er novembre</p> </div> <div class="detail"> <p>Armistice 1918</p> <p><?= $year->armistice($year->year) ?> 11 novembre</p> </div> <div class="detail"> <p>Noël</p> <p><?= $year->noel($year->year) ?> 25 décembre</p> </div> </div> </div> </section> </div> <footer> <p>Copyright © calendrier (2023-<span class="cpy"></span></span>). Tous droits réservés</p> </footer> </body> </html>
2 - calend.css
*, ::before, ::after { margin: 0; padding: 0; box-sizing: border-box; } ::-webkit-scrollbar { display: none; } html, body { width: 100%; height: 100%; } body { height: 100vh; font-family: 'Roboto', sans-serif; font-style: italic; background-color: #f1f1f1; overflow: hidden; } a { text-decoration: none; color: inherit; } a:hover { opacity: 0.7; } .container { display: flex; flex-direction: column; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; bottom: 200px; z-index: 1030; } header { padding-bottom: 10px; display: flex; justify-content: space-between; color: #0d6efd; font-weight: 800; border-bottom: 2px solid #023E8A; } .datetime { margin-top: 2.5px; margin-left: 2.5px; padding: 10px; font-size: 1rem; } h1 { margin-top: 2.5px; padding: 10px; height: 60px; font-size: 1.75rem; font-weight: 400; color: #0d6efd; } .time { margin-top: 2.5px; margin-right: 2.5px; padding: 10px; height: 40px; font-size: 1rem; text-transform: lowercase; } nav { padding: 10px 0 10px; display: flex; justify-content: center; border-bottom: 2px solid #023e8a; /* background-color: #ffd700;*/ } .btn { margin-right: 10px; padding: 10px 0 10px; width: 200px; font-size: 1.25rem; font-style: italic; color: #f1f1f1; text-align: center; border: none; border-radius: 8px; outline: none; cursor: pointer; } .btn:hover { opacity: 0.7; } .btn:first-child, .btn:last-child { width: 40px; } .btn-primary { background-color: #0d6efd; } .btn-success { background-color: #0d6efd; } .btn-danger { background-color: #ff0054; } section { padding: 10px 0 10px; display: flex; justify-content: center; background-color: #f1f1f1; } .ferie { display: flex; justify-content: center; color: #f1f1f1; } .calend { display: block; float: left; width: 18rem; margin-right: 10px; } .cal-top { width: 18rem; font-style: italic; color: #f1f1f1; } .cal-top .top1 { padding: 10px; font-size: 1.25rem; text-align: center; background: #023e8a; border-bottom: 1px solid #f1f1f1; border-top-left-radius: 10px; border-top-right-radius: 10px; } .cal-top .top2 { padding: 5px 0 5px 5px; font-size: 1.25rem; background: #023e8a; } .caldat { float: left; width: 9rem; text-align: center; } .calday { display: flex; float: left; width: 3rem; padding-left: 20px; text-align: right; } .calsem { margin-left: 25px; margin-right: 5px; padding-left: 20px; width: 3rem; text-align: right; } .caldet { display: flex; flex-direction: column; } .day { display: flex; flex-direction: row; justify-content: space-between; color: #fff; font-weight: 400; background: #003366; } .day:first-child { padding-top: 10px; } .day:last-child { padding-bottom: 10px; border-bottom: 1px solid #f1f1f1; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; } .cal_date { width: 60%; margin-left: 8px; } .cal_day { width: 40%; text-align: right; } .cal_num_day { width: 50%; text-align: right; margin-right: 10px; } .cal_num_week { width: 50%; text-align: right; margin-right: 10px; } .red { color: #f00; } .green { color: #0f0; font-weight: 700; } .blue { color: aqua; font-weight: 700; } .content { width: 100%; display: flex; flex-direction: column; } .top-header { width: 100%; height: 2rem; font-weight: 400; border-bottom: 1px solid #000; } .top-header p { margin-right: 10px; font-size: 1.5rem; font-weight: 400; text-align: center; } #sect03 { margin: 20px auto; width: 760px; color: #fff; background-color: #023e8a; border-bottom: none; border-radius: 10px; } .feries-top { width: 100%; min-width: 760px; height: 60px; color: #000; font-weight: 300; text-align: left; } .feries-top h3 { width: 1.5rem; font-weight: 700; } .ferie_det { background-color: #003366; } .detail { display: flex; justify-content: space-between; margin-bottom: 8px; } .detail p:first-child { margin-left: 10px; } .detail p:last-child { margin-right: 10px; } .feries-body h3 { font-size: 1.25rem; font-weight: 400; } .body-right { margin-right: 10px; } footer { position: fixed; height: 25px; right: 0; bottom: 0; left: 0; text-align: center; color: #fff; font-weight: 400; border-top: 2px solid #023e8a; background-color: #0d6efd; } footer p { line-height: 1rem; font-size: 1rem; font-weight: 700; }
3 - classe Year.php
<?php namespace App; use \DateTime; use \DateInterval; use \IntlDateFormatter; use \DateTimeImmutable; class Year { // Tableau des jours et des mois public $days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi']; public $months = [' ', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre']; public int $year; public string $now; private $feries; // Variables private int $daysInMonths; private $source; // Jours fériés /** * Constructeur * @param int|null $month [description] * @param int|null $year [description] */ public function __construct(?int $year = null) { if ($year === null) { $dt = new DateTime(); $year = intval($dt->format('Y')); } $this->year = $year; $this->now = date('Y-m-d'); // Tableau des jours fériés $this->feries = $this->getFeries($this->year); } /** * Construction des lignes de source * @return string */ public function getFirstSem($year): string { $date = new DateTime($year . '-01-01'); for ($month = 1; $month <= 6; $month++) { $this->daysInMonths = $date->format('t'); $this->source .= '<div class="calend">'; $this->source .= '<div class="cal-top">'; $this->source .= '<div class="top1">' . $this->months[$month] . '</div>'; $this->source .= '<div class="top2">'; $this->source .= '<span class="caldat">date'; $this->source .= '</span>'; $this->source .= '<span class="calday">jour'; $this->source .= '</span>'; $this->source .= '<span class="calsem">sem</span>'; $this->source .= '</span>'; $this->source .= '</div>'; $this->source .= '</div>'; for ($day = 1; $day <= $this->daysInMonths; $day++) { if (in_array($date->format('Y-m-d'), $this->feries)) { $this->source .= '<div class="day green">'; } elseif (($this->days[$date->format('w')] === 'Dimanche')) { $this->source .= '<div class="day red">'; } elseif ($date->format('Y-m-d') === $this->now) { $this->source .= '<div class="day blue">'; } else { $this->source .= '<div class="day">'; } $this->source .= '<span class="cal_date">'; $this->source .= $this->days[$date->format('w')]; $this->source .= '</span>'; $this->source .= $date->format('d'); $this->source .= '</span>'; $this->source .= '<span class="cal_num_day">'; $this->source .= ($date->format('z')+1) < 10 ? '0' . $date->format('z')+1 : $date->format('z')+1; $this->source .= '</span>'; $this->source .= '<span class="cal_num_week">'; $this->source .= $date->format('W'); $this->source .= '</span>'; $this->source .= '</div>'; $date->add(new DateInterval('P1D')); } $this->source .= '</div>'; } $this->source .= '</div>'; return $this->source; } /** * Construction des lignes de source * @return string */ public function getSecondSem($year): string { $this->source = ''; $date = new DateTime($year . '-07-01'); for ($month = 7; $month <= 12; $month++) { $this->daysInMonths = $date->format('t'); $this->source .= '<div class="calend">'; $this->source .= '<div class="cal-top">'; $this->source .= '<div class="top1">' . $this->months[$month] . '</div>'; $this->source .= '<div class="top2">'; $this->source .= '<span class="caldat">date'; $this->source .= '</span>'; $this->source .= '<span class="calday">jour'; $this->source .= '</span>'; $this->source .= '<span class="calsem">sem</span>'; $this->source .= '</span>'; $this->source .= '</div>'; $this->source .= '</div>'; for ($day = 1; $day <= $this->daysInMonths; $day++) { if (in_array($date->format('Y-m-d'), $this->feries)) { $this->source .= '<div class="day green">'; } elseif (($this->days[$date->format('w')] === 'Dimanche')) { $this->source .= '<div class="day red">'; } elseif ($date->format('Y-m-d') === $this->now) { $this->source .= '<div class="day blue">'; } else { $this->source .= '<div class="day">'; } $this->source .= '<span class="cal_date">'; $this->source .= $this->days[$date->format('w')]; $this->source .= '</span>'; $this->source .= $date->format('d'); $this->source .= '</span>'; $this->source .= '<span class="cal_num_day">'; $this->source .= ($date->format('z')+1) < 10 ? '0' . $date->format('z')+1 : $date->format('z')+1; $this->source .= '</span>'; $this->source .= '<span class="cal_num_week">'; $this->source .= $date->format('W'); $this->source .= '</span>'; $this->source .= '</div>'; $date->add(new DateInterval('P1D')); } $this->source .= '</div>'; } $this->source .= '</div>'; return $this->source; } /** * Liste des jours fériés * @param [type] $year [description] * @return [type] [description] */ public function getFeries($year) { // Tableau des jours fériés $feries = [$year . '-01-01', $year . '-05-01', $year . '-05-08', $year . '-07-14', $year . '-08-15', $year . '-11-01', $year . '-11-11', $year . '-12-25']; // Date de base $easter = date('Y-m-d', easter_date($year)); $easter = new DateTimeImmutable($easter); // Pâques $base = new DateTime("$year-03-21"); $days = easter_days($year); $paques = $base->add(new \DateInterval("P{$days}D")); // Dates liées à pâques $lpaq = $easter->add(new \DateInterval('P2D')); $asc = $easter->add(new \DateInterval('P40D')); $pent = $easter->add(new \DateInterval('P50D')); $lpent = $easter->add(new \DateInterval('P51D')); // Chargement du tableau array_push($feries, $paques->format('Y-m-d')); array_push($feries, $lpaq->format('Y-m-d')); array_push($feries, $asc->format('Y-m-d')); array_push($feries, $pent->format('Y-m-d')); array_push($feries, $lpent->format('Y-m-d')); return $feries; } /** * Envoit l'année suivante * @return Year */ public function nextYear(): Year { $year = $this->year + 1; return new Year($year); } /** * Envoit l'année précédente * @return Year */ public function prevYear(): Year { $year = $this->year - 1; return new Year($year); } /** * Récupèrer le jour du 1er janvier * @param $year * @return string */ public function oneJan($year): string { $date = new DateTime($year.'-01-01'); return $this->days[$date->format('w')]; } public function paques($year) { // Date de base $easter = date('Y-m-d', easter_date($year)); $easter = new DateTimeImmutable($easter); // Pâques $base = new DateTime("$year-03-21"); $days = easter_days($year); $paques = $base->add(new \DateInterval("P{$days}D")); $lpaq = $easter->add(new \DateInterval('P2D'))->format('d'); $mois = $easter->add(new \DateInterval('P2D'))->format('n'); $lundiPaques = intval($easter->add(new \DateInterval('P2D'))->format('w')); return $lpaq . ' ' . $this->months[$mois]; } public function travail($year) { $date = new DateTime($year.'-05-01'); return $this->days[$date->format('w')]; } public function victoire($year) { $date = new DateTime($year.'-05-08'); return $this->days[$date->format('w')]; } public function ascension($year) { // Date de base $easter = date('Y-m-d', easter_date($year)); $easter = new DateTimeImmutable($easter); // Ascension $asc = $easter->add(new \DateInterval('P40D')); $jo = $this->days[$asc->format('w')]; $dt = $asc->format('d'); $mois = $asc->format('n'); return $dt . ' ' . $this->months[$mois]; } public function pentecote($year) { // Date de base $easter = date('Y-m-d', easter_date($year)); $easter = new DateTimeImmutable($easter); // Ascension $pent = $easter->add(new \DateInterval('P51D')); $jo = $this->days[$pent->format('w')]; $dt = $pent->format('d'); $mois = $pent->format('n'); return $dt . ' ' . $this->months[$mois]; } public function assomption($year) { $date = new DateTime($year.'-08-15'); $day = $date->format('w'); return $this->days[$day]; } public function toussaint($year) { $date = new DateTime($year.'-11-01'); $day = $date->format('w'); return $this->days[$day]; } public function armistice($year) { $date = new DateTime($year.'-11-11'); $day = $date->format('w'); return $this->days[$day]; } public function noel($year) { $date = new DateTime($year.'-12-25'); $day = $date->format('w'); return $this->days[$day]; } }
4 - script calend.js
// Déclarations const previous = document.querySelector('#prev'), first = document.querySelector('#premier'), second = document.querySelector('#second'), feries = document.querySelector('#feries'), next = document.querySelector('#next'), sect01 = document.querySelector('#sect01'), sect02 = document.querySelector('#sect02'), sect03 = document.querySelector('#sect03'), opt = { month: 'numeric' } month = new Date().toLocaleDateString('fr-FR', opt) // Afficher premier ou second semestre suivant le mois if (month <= 6) { sect01.style.display = 'flex' sect02.style.display = 'none' sect03.style.display = 'none' } else { sect01.style.display = 'none' sect02.style.display = 'flex' sect03.style.display = 'none' } // Afficher premier semestre au click first.addEventListener('click', () => { sect01.style.display = 'flex' sect02.style.display = 'none' sect03.style.display = 'none' }) second.addEventListener('click', () => { sect01.style.display = 'none' sect02.style.display = 'flex' sect03.style.display = 'none' }) feries.addEventListener('click', () => { sect01.style.display = 'none' sect02.style.display = 'none' sect03.style.display = 'flex' })
5 - script date.prototype.js
// Fonctions date /** * Date complète * @returns {string} */ Date.prototype.getFullDate = function () { const date = new Date(), dateOpt = { weekday: 'long', year: 'numeric', month: 'long', day: '2-digit' } return `${this.toLocaleDateString('fr-FR', dateOpt)}` } /** * Heure complète * @returns {string} */ Date.prototype.getFullTime = function () { const date = new Date(), timeOpt = { hour: '2-digit', minute:'2-digit', second: '2-digit', hour12: true } return `${this.toLocaleTimeString('fr-FR', timeOpt)}` } /** * Numéro de la semaine dans l'année (01...52,53) * @returns {string} */ Date.prototype.getWeek = function () { const d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate())), dayNum = d.getUTCDay() || 7 d.setUTCDate(d.getUTCDate() + 4 - dayNum) const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)) return Math.ceil((((d - yearStart) / 86400000) + 1) / 7).toString().padStart(2, '0') } /** * Numéro du jour dans l'année (01...365,366) * @returns {string} */ Date.prototype.getDayOfYear = function () { const onejan = new Date(this.getFullYear(), 0, 1) return Math.ceil((this - onejan) / 86400000).toString().padStart(2, '0') } /** * L'année est-elle bissextile ? * @returns {boolean} */ Date.prototype.isLeap = function () { const date = new Date() return true ? ((this.getFullYear() % 400 === 0) || (this.getFullYear()% 100 !== 0)) && ((this.getFullYear() % 4) === 0) : false } /** * Nombre de jours restant * @returns {integer} */ Date.prototype.getLeftDays = function () { const date = new Date() return (this.isLeap() ? 366 : 365) - this.getDayOfYear() }
6 - script date.time.js
// Constantes const now = new Date() // Date du jour document.querySelector('.date').textContent = now.getFullDate() // Jour dans l'année en cours document.querySelector('.num-day').textContent = `${'(Jour:'} ${now.getDayOfYear()}${')'}` // Semaine dans l'année en cours document.querySelector('.num-week').textContent = `${'(Semaine:'} ${now.getWeek()}${')'}` // Nombre de jours restant est supérieur à 1 ou égale à 0 document.querySelector('.reste').textContent = (now.getLeftDays() === 0 ? '(Dernier jour de l\'année)' : (now.getLeftDays() === 1) ? '(Reste: ' + now.getLeftDays() + ' jour)' : '(Reste: ' + now.getLeftDays() + ' jours)') // Copyright document.querySelector('.cpy').textContent = new Date().getFullYear() // Affichage de l'heure const refreshTime = () => { document.querySelector('.time').textContent = new Date().getFullTime() } refreshTime() setInterval(refreshTime, 1000)
Tout ça marche bien, sauf quand l'année est inférieure à 1970 ou supérieure à 2036.
Merci de votre aide
9 mars 2023 à 13:09
As-tu pu déterminer quelle partie du code est déficiente?
9 mars 2023 à 13:39
Comme expliqué en #2, tu ne peux pas utiliser des fonctions standards pour les années antérieures à 1970: tu dois faire les calculs toi-même, ou trouver quelqu'un qui a déjà fait ce travail et qui te permet de réutiliser son travail.
9 mars 2023 à 14:08
Aucune partie du code n'est déficiente, seules les année < 1970 ou > 2036 posent un problème, comment les traiter ?
Il semble bien que les temps soient enregistrés dans le format supporté par Unix, soit un entier signé de 32 bits.
Le petit programme Python suivant montre qu'on s'approche de cette limite à la fin de 2036
from math import log2
j = 24 * 60 * 60 # Nombre de secondes dans une journée.
a = j * 365 # Durée normale d'une année.
p = 2036 - 1970 + 1 # Nombre d'années.
b = (p+3) // 4 # Nombre d'années bissextiles.
d = a * p + b * j # Nombre de secondes pour la période considérée.
c = 2**31 - 1 # Limite pour un entier signé à 32 bits.
print(j, a, p, b, d, c, sep=', ')
86400, 31536000, 67, 17, 2114380800, 2147483647
Ton code est très long. Pourquoi ne pas faire un essai avec le minimum de code, en précisant bien ce que tu veux faire?
Et si ça t'intéresse, la fin du monde arrivera le 19 janvier 2038 à 03:14:07 selon ce registre. :)
Pour le calendrier d'une année, on a seulement besoin de savoir le jour de la semaine du premier janvier,
et si l'année est bissextile (ça c'est facile).
Puisque PHP ressemble un peu à C, j'ai écrit mon code en C.
Il ne fonctionnera que pour le calendrier Grégorien (pas le calendrier Julien).
Les jours sont numérotés de 0 à 6 (0 étant un dimanche).
#include <stdio.h>
int bissextile(int annee) {
if(annee % 400 == 0) return 1;
if(annee % 100 != 0 && annee % 4 == 0) return 1;
return 0;
}
int distance(int ref_date, int cur_date) {
int jours = 0;
while(ref_date < cur_date) {
jours += 365 + bissextile(ref_date);
ref_date++;
}
return jours;
}
int main(void) {
int ref = 2022;
int cur;
scanf("%d", &cur);
int jours;
// Si l'année courante est avant la date de référence, la distance sera négative (plus simple pour le calcul).
if(cur < ref) jours = - distance(cur, ref);
else jours = distance(ref, cur);
// En 2022, le premier janvier était un samedi (jour 6)
// On a besoin des deux % 7 pour les distances négatives.
int jourSemaine = (6 + jours%7 + 7) % 7;
printf("%d\n", jourSemaine);
}