Algoritmo: Como saber si un año es bisiesto

Algoritmo: Como saber si un año es bisiesto

Si estamos programado calendarios o alguna aplicación relacionada con años

Si estamos programando calendarios o alguna aplicación relacionada con años, es importante conocer el algoritmo que nos permitirá saber si un año es bisiesto o no.


Índice de contenidos


El algoritmo

Un año es bisiesto según el Calendario Gregoriano (vigente desde 1582) si cumple estas reglas en orden:

  1. El año debe ser igual o mayor a 1582. Si es inferior, se descarta — el calendario gregoriano no existía antes.
  2. Si el año no es divisible entre 4 → año normal (365 días).
  3. Si el año no es divisible entre 100 → año bisiesto (366 días). ✅
  4. Si el año es divisible entre 400 → año bisiesto (366 días). ✅
  5. En cualquier otro caso → año normal (365 días).

Por qué existen las excepciones del 100 y el 400: Un año solar no tiene exactamente 365,25 días sino 365,2422. Sin las correcciones del 100 y el 400, el calendario acumularía un error de ~3 días cada 400 años. Por eso el año 1900 no fue bisiesto, pero el 2000 lo fue.

Diagrama flujo algoritmo año bisiesto


Ejemplos en lenguajes de programación

1. JavaScript

Ideal para validaciones en el frontend o en Node.js.

function esBisiesto(año) {
  if (año < 1582) return false;
  return (año % 4 === 0 && año % 100 !== 0) || (año % 400 === 0);
}

// Ejemplos
console.log(esBisiesto(2000)); // true  ✅
console.log(esBisiesto(1900)); // false ❌
console.log(esBisiesto(2024)); // true  ✅
console.log(esBisiesto(2023)); // false ❌

Versión con Date (alternativa nativa usando el truco del 29 de febrero):

function esBisiestoDate(año) {
  return new Date(año, 1, 29).getDate() === 29;
}

2. PHP

Muy usado en aplicaciones web y sistemas de gestión de citas o reservas.

<?php
function esBisiesto(int $año): bool {
    if ($año < 1582) return false;
    return ($año % 4 === 0 && $año % 100 !== 0) || ($año % 400 === 0);
}

// Ejemplos
var_dump(esBisiesto(2000)); // bool(true)  ✅
var_dump(esBisiesto(1900)); // bool(false) ❌
var_dump(esBisiesto(2024)); // bool(true)  ✅
var_dump(esBisiesto(2023)); // bool(false) ❌

Versión con checkdate (función nativa de PHP):

<?php
function esBisiestoNativo(int $año): bool {
    return checkdate(2, 29, $año);
}

3. Python

Python incluye soporte nativo en el módulo calendar.

def es_bisiesto(año: int) -> bool:
    if año < 1582:
        return False
    return (año % 4 == 0 and año % 100 != 0) or (año % 400 == 0)

# Ejemplos
print(es_bisiesto(2000))  # True  ✅
print(es_bisiesto(1900))  # False ❌
print(es_bisiesto(2024))  # True  ✅
print(es_bisiesto(2023))  # False ❌

Versión con calendar (módulo estándar):

import calendar

print(calendar.isleap(2024))  # True ✅

4. Java

public class AñoBisiesto {

    public static boolean esBisiesto(int año) {
        if (año < 1582) return false;
        return (año % 4 == 0 && año % 100 != 0) || (año % 400 == 0);
    }

    public static void main(String[] args) {
        System.out.println(esBisiesto(2000)); // true  ✅
        System.out.println(esBisiesto(1900)); // false ❌
        System.out.println(esBisiesto(2024)); // true  ✅
        System.out.println(esBisiesto(2023)); // false ❌
    }
}

Versión con Year (API de fechas moderna, Java 8+):

import java.time.Year;

boolean bisiesto = Year.of(2024).isLeap(); // true ✅

5. C#

using System;

public class AñoBisiesto {
    public static bool EsBisiesto(int año) {
        if (año < 1582) return false;
        return (año % 4 == 0 && año % 100 != 0) || (año % 400 == 0);
    }

    static void Main() {
        Console.WriteLine(EsBisiesto(2000)); // True  ✅
        Console.WriteLine(EsBisiesto(1900)); // False ❌
        Console.WriteLine(EsBisiesto(2024)); // True  ✅
        Console.WriteLine(EsBisiesto(2023)); // False ❌
    }
}

Versión con DateTime (método nativo):

bool bisiesto = DateTime.IsLeapYear(2024); // true ✅

6. Ruby

def bisiesto?(año)
  return false if año < 1582
  (año % 4 == 0 && año % 100 != 0) || (año % 400 == 0)
end

puts bisiesto?(2000) # true  ✅
puts bisiesto?(1900) # false ❌
puts bisiesto?(2024) # true  ✅
puts bisiesto?(2023) # false ❌

Versión nativa con Date:

require 'date'
puts Date.leap?(2024) # true ✅

7. Go

package main

import "fmt"

func esBisiesto(año int) bool {
    if año < 1582 {
        return false
    }
    return (año%4 == 0 && año%100 != 0) || (año%400 == 0)
}

func main() {
    fmt.Println(esBisiesto(2000)) // true  ✅
    fmt.Println(esBisiesto(1900)) // false ❌
    fmt.Println(esBisiesto(2024)) // true  ✅
    fmt.Println(esBisiesto(2023)) // false ❌
}

Fórmulas para Excel y Google Sheets

El número de serie en Excel parte de 1900, que fue tratado incorrectamente como bisiesto. Las fórmulas siguientes lo tienen en cuenta.

Fórmula universal

Funciona en Excel y Google Sheets. Escribe el año en la celda A1.

En español:

=SI(A1<1582,"No gregoriano",SI(O(Y(RESIDUO(A1,4)=0,RESIDUO(A1,100)<>0),RESIDUO(A1,400)=0),"✅ Bisiesto","❌ No bisiesto"))

En inglés (Excel en inglés / Google Sheets):

=IF(A1<1582,"Not Gregorian",IF(OR(AND(MOD(A1,4)=0,MOD(A1,100)<>0),MOD(A1,400)=0),"✅ Leap year","❌ Not leap year"))

Fórmula compacta

Si solo necesitas un TRUE/FALSE para usar el resultado en otra fórmula:

En español:

=Y(A1>=1582,O(Y(RESIDUO(A1,4)=0,RESIDUO(A1,100)<>0),RESIDUO(A1,400)=0))

Truco con DAY — aprovecha que el 29 de febrero solo existe en años bisiestos:

=DIA(FECHA(A1,3,1)-1)=29

Esta fórmula construye el 1 de marzo del año dado, retrocede un día y comprueba si ese día es el 29. Devuelve VERDADERO o FALSO sin lógica modular.


Resaltar bisiestos con formato condicional

Para destacar automáticamente las filas bisiestas en un rango de años (A2:A100):

  1. Selecciona el rango A2:A100
  2. Ve a Formato → Formato condicional
  3. Elige «La fórmula es» e introduce:
=Y(A2>=1582,O(Y(RESIDUO(A2,4)=0,RESIDUO(A2,100)<>0),RESIDUO(A2,400)=0))
  1. Elige el color de relleno que prefieras y aplica.

Años bisiestos de referencia

Útiles para probar tus implementaciones:

Año ¿Bisiesto? Motivo
2000 ✅ Sí Divisible entre 400
1900 ❌ No Divisible entre 100 pero no entre 400
2024 ✅ Sí Divisible entre 4 y no entre 100
2100 ❌ No Divisible entre 100 pero no entre 400
1600 ✅ Sí Divisible entre 400
1581 ❌ No Anterior al calendario gregoriano
2400 ✅ Sí Divisible entre 400