Une erreur historique et comment la résoudre
TL;DR : La plupart des langages ne parviennent pas à trouver le comportement correct pour le calcul des années bissextiles.
Avis de non-responsabilité : même si j'ai fait de mon mieux pour fournir des informations précises sur différents langages de programmation, je reconnais que je ne suis peut-être pas un expert dans tout le monde. Si vous repérez une erreur ou n'êtes pas d'accord avec un point, veuillez laisser un commentaire respectueux et j'y remédierai dans les plus brefs délais.
Déterminer si une année est bissextile (ou non) est un problème mathématique simple.
Chaque étudiant peut le résoudre comme premier devoir de programmation.
Pour simplifier le problème, supposons qu'une année est bissextile lorsqu'elle est divisible par 4, sauf si elle est également divisible par 100, mais qu'elle est bissextile si elle est divisible par 400.
Le monde réel et la mécanique cosmique sont un peu plus compliqués, mais cela dépasse le cadre de cet article.
Explorons comment plusieurs langages de programmation résolvent ce problème :
PHP :
<?php $yearNumber = 2024; $isLeap = date('L', mktime(0, 0, 0, 1, 1, $yearNumber));
SQL (PostgreSQL) :
SELECT (EXTRACT(year FROM TIMESTAMP '2024-02-29') IS NOT NULL) AS is_leap_year;
Ces langages tentent de créer un jour bissextile valide (ou invalide) et d'exploiter des valeurs véridiques .
Ce hack viole le principe du fail-fast et abuse de l'erreur d'un milliard de dollars .
Essayer de créer une date invalide devrait générer une exception dans les langages sérieux puisque cela se produit dans le domaine du monde réel .
Effectuer d’autres actions, comme dissimuler des erreurs sous la surface, enfreint le principe du moindre étonnement.
Ada :
function Is_Leap_Year (Year : Integer) return Boolean is begin return (Year mod 4 = 0 and then Year mod 100 /= 0) or else (Year mod 400 = 0); end Is_Leap_Year;
C/C++ :
bool isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); }
Aller:
package main import ( "fmt" "time" ) func isLeapYear(year int) bool { return year%4 == 0 && (year%100 != 0 || year%400 == 0) }
Haskel :
import Data.Time.Calendar (isLeapYear) let year = 2024 let isLeap = isLeapYear year
JavaScript/TypeScript :
function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0); }
Julia:
using Dates year = 2024 isleap(year)
Lua :
local year = 2024 local isLeap = (year % 4 == 0 and year % 100 ~= 0) or (year % 400 == 0)
MATLAB :
year = 2024; isLeap = mod(year, 4) == 0 && (mod(year, 100) ~= 0 || mod(year, 400) == 0);
Objectif c:
int yearNumber = 2024; BOOL isLeap = (yearNumber % 4 == 0 && yearNumber % 100 != 0) || (yearNumber % 400 == 0);
PowerShell :
$yearNumber = 2024 $isLeap = ($yearNumber % 4 -eq 0 -and $yearNumber % 100 -ne 0) -or ($yearNumber % 400 -eq 0)
Rouiller:
fn is_leap_year(year: i32) -> bool { (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) }
Petite conversation :
| yearNumber | yearNumber := 2024. (yearNumber \\ 4 = 0) and: [(yearNumber \\ 100 ~= 0) or: [ yearNumber \\ 400 = 0 ]]
Les langues ci-dessus ne fournissent pas de support natif.
Vous devez définir des fonctions globales ou utiliser des helpers .
PHP (encore une fois) :
<?php $yearNumber = 2024; $isLeap = checkdate(2, 29, $yearNumber);
R :
leap_year(2024)
Rubis:
year = 2024 is_leap = Date.leap?(year)
Rapide:
let yearNumber = 2024 let isLeap = Calendar.current.isDateInLeapYear( Date(timeIntervalSince1970: TimeInterval(yearNumber)))
Ces langages utilisent des fonctions globales pour vérifier si une année est bissextile.
Ces méthodes globales d’utilité placent par erreur la responsabilité au mauvais endroit (un point d’accès global).
C# :
int yearNumber = 2024; bool isLeap = System.DateTime.IsLeapYear(yearNumber);
Dard:
import 'package:intl/intl.dart'; var year = 2024; var isLeap = DateTime(year).isLeapYear;
Perl :
use Time::Piece; my $yearNumber = 2024; my $isLeap = Time::Piece ->strptime("$yearNumber-01-01", "%Y-%m-%d")->leapyear;
Python:
import calendar leap = calendar.isleap(2024)
Visual Basic .NET :
Dim year As Integer = 2024 Dim isLeap As Boolean = DateTime.IsLeapYear(year)
Ces langages utilisent des assistants comme bibliothèques pour vérifier si une année est bissextile.
Le responsable égaré n'est pas présent dans un objet réel mais dans un sac de fonctions liées à DateTime .
Java:
int yearNumber = 2024; boolean isLeap = java.time.Year.of(yearNumber).isLeap();
Kotlin :
val yearNumber = 2024 val isLeap = java.time.Year.of(yearNumber).isLeap
Échelle :
val year = 2024 val isLeap = java.time.Year.of(year).isLeap
Ces langues s'appuient sur l' Année pour vérifier s'il s'agit d'un saut.
Le protocole est plus proche du monde réel dans la bijection
Notez qu'ils créent des objets Year et non des objets Integer car cela briserait également la bijection .
A Year a un protocole différent de celui d'un nombre entier, et modéliser une Year comme un entier serait également une odeur d'optimisation prématurée et un symptôme de mélange du quoi et du comment .
Un Year peut indiquer s'il s'agit d'un saut (un entier ne devrait pas le faire) et peut vous renseigner sur ses mois (qui sont des Months , et non des entiers de base 0 , des entiers de base 1 ou des chaînes).
À l'inverse, les capacités d'un Integer s'étendent aux opérations arithmétiques telles que la multiplication et l'exponentiation.
Représenter un point dans le temps sous la forme d'un float , d'un entier ou de tout autre type de données a des conséquences.
Vous pouvez diviser un instant dans le monde réel en fractions infimes (mais pas trop petites )
L'utilisation de flotteurs n'est pas une option valide.
0,01 + 0,02 n'est pas 0,03, et cela a des conséquences terribles sur les points flottants dans le temps.
Nous parlons d'années bissextiles.
Quels sont les besoins à savoir si une année est bissextile ?
Les mécanismes de date et d'heure que vous modélisez doivent connaître le successeur du 28 février 2024.
Mais ce n'est PAS votre problème.
Conformément au principe de dissimulation des informations, vous devez laisser la responsabilité sous forme de protocole privé.
Il n’existe pas de solution miracle .
Utilisez votre langue à bon escient.
Aujourd'hui, nous sommes le 29 février, un jour bissextile pour faire une pause et réfléchir aux outils que vous utilisez quotidiennement.
Rendez-vous dans 4 ans.