Cómo calcular qué día de la semana fue

Vamos a ver en este post una forma para saber qué día de la semana fue cualquier fecha. El algoritmo consiste en calcular ciertos coeficientes a partir de la fecha (día, mes y año) y efectuar ciertos cálculos con ellos para quedarnos con un número entre 0 y 6. Después sabiendo qué número es el que corresponde a cada día conseguiremos resolver el problema. Vamos a explicar el método llevando a la vez un ejemplo: mi cumpleaños del año que viene, 1 de Mayo de 2007, que de antemano os digo que es martes:

1.- El siglo: El primer coeficiente que necesitamos, llamémosle A, lo conseguimos con el siglo al que pertenece el año de la fecha siguiendo esta tabla:

1700…1799 1800…1899 1900…1999 2000…2099 2100…2199 2200…2299
+5 +3 +1 0 -2 -4

En nuestro ejemplo obtenemos que A = 0

2.- Año: Tomamos los dos últimos dígitos del año en cuestión y a ese número de dos cifras le sumamos un cuarto del mismo (despreciando los decimales). Eso nos proporciona el segundo coeficiente, digamos B.

En nuestro caso: 7/4 = 1′75. Despreciamos los decimales y nos queda 1. Como los dos últimos dígitos son 07 tenemos que B = 8.

3.- Años bisiestos: Éstos son los que cumplen que sus dos últimas cifras forman un múltiplo de 4 (por ejemplo, 1992 o 2004) excepto los terminados en 00. Entre estos últimos sólo son bisiestos los múltiplos de cuatrocientos (por ejemplo 2000). Nuestro tercer coeficiente, C depende de ellos: si el año es bisiesto, y el mes es enero o febrero el coeficiente será C = –1. En cualquier otro caso C = 0.

En nuestro ejemplo, como 2007 no es bisiesto tenemos que C = 0.

4.- Mes: El cuarto coeficiente, D, nos lo da la siguiente tabla:

Enero Feb. Marzo Abril Mayo Junio Julio Agosto Sept. Oct. Nov. Dic.
6 2 2 5 0 3 5 1 4 6 2 4

En nuestro ejemplo, como el mes es mayo, tenemos que D = 0.

5.- Día: El quinto coeficiente, E, es simplemente el día en cuestión. En este caso E = 1.

6.- Algoritmo: Tomamos todos los coeficientes calculados y los sumamos. Y después calculamos el resto módulo 7 del número que obtenemos. Eso lo podemos hacer restando 7 al resultado tantas veces como sea necesario hasta obtener un número entre 0 y 6 que llamaremos R.

En nuestro ejemplo:

A + B + C + D + E = 0 + 8 + 0 + 0 + 1 = 9
9 – 7 = 2

Por tanto R = 2

7.- Resultado: La asignación de números a cada día de la semana es la siguiente:

Lunes Martes Miércoles Jueves Viernes Sábado Domingo
1 2 3 4 5 6 0

Por tanto, como en nuestro ejemplo R = 2 tenemos que:

el 1 de Mayo de 2007 será martes

como en realidad ocurre.

Espero que os haya parecido interesante.

Fuente: Ese Primo

Share

19 comentarios

  1. homero | 22 de agosto de 2006 | 14:59

    Vótalo Thumb up 0

    Existe un algoritmo llamado “doomsday” para calcular el día de la semana de cualquier fecha, y que es muy similar al que muestras acá, con la gracia adicional de que está pensado para ser aprendido de memoria. En esta página:

    http://rudy.ca/doomsday.html

    explican el algoritmo y enseñan la forma de memorizarlo. En su momento lo aprendí, y funciona bastante bien.

  2. juan23 | 23 de agosto de 2006 | 15:49

    Vótalo Thumb up 0

    y las adaptaciones anteriores … cambio del calendario juliano al gregoriano?

  3. ^DiAmOnD^ | 24 de agosto de 2006 | 10:51

    Vótalo Thumb up 0

    Vaya, buena pregunta juan23. Habría que ver cómo se realizó el cambio para adaptar el método con las modificaciones pertinentes. Supongo que no sería demasiado complicado

  4. fede | 7 de octubre de 2006 | 16:21

    Vótalo Thumb up 0

    El cambio de calendario se realizó en España y países catolicos el mes de octubre de 1582, que solo tuvo 20 días. Ese mes, el día siguiente al jueves 4 fué viernes 15.
    En el resto del mundo el cambió fué produciendose en los siguientes siglos (hasta el XX), por ejemplo en Inglaterra y colonias fué en 1752 (el dia siguiente al 3/9 fué 14/9).
    El nuevo calendario introdujo las reglas actuales para los años multiplo de 100 y 400.

    Esto solo afecta al cálculo del coeficiente “A”, que debería ser entonces:

    Siendo cc los 2 primeros digitos del año, (parte entera de año/100)
    Si el dato >= 15/10/1582, A = 5, 3, 1 ó 0 según sea cc (mod 4) 1, 2, 3 ó 0.
    Si el dato

  5. fede | 8 de octubre de 2006 | 09:48

    Vótalo Thumb up 0

    Si la fecha es anterior a 15/10/1582, A = 19 – cc

  6. Gabriela | 28 de octubre de 2006 | 23:09

    Vótalo Thumb up 0

    Hola, me interesa saber qué dia de la semana fue el 7 de abril del 1972. O bien, tener todo el mes completo del mes de Abril de 1972. Si es que lo tienen les agradecería me lo hagan llegar.
    Gracias.

  7. ^DiAmOnD^ | 29 de octubre de 2006 | 05:21

    Vótalo Thumb up 0

    Gabriela utilizando la fórmula que se detalla en el post, y si no me he equivocado, el 7 de abril de 1972 fue viernes. Que lo haga alguien más a ver si es correcto.

  8. fede | 29 de octubre de 2006 | 10:19

    Vótalo Thumb up 0

    El mes completo se puede ver, por ejemplo, aquí.

  9. Jose23 | 27 de septiembre de 2013 | 18:00

    Vótalo Thumb up 0

    cual es el mes que cambiaria de valor si es bisiesto es enero o febrero?

  10. Jose23 | 27 de septiembre de 2013 | 18:06

    Vótalo Thumb up 0

    El numero con el que voy a restar el total de valores calculados siempre va ser 7?
    URGENTE!!!!!!!!!!!

  11. charlie | 14 de enero de 2014 | 21:30

    Vótalo Thumb up 0

    me gustaria que ampliasen el coeficiente “A” para siglos anteriores al XVII hasta por lo menos el siglo II antes de cristo, o como se calcula, ya que no me ha quedado claro, el primer comentario de “Fede”

  12. Víctor | 23 de enero de 2014 | 05:46

    Vótalo Thumb up 0

    Tal vez ayude un poco de código en pascal (delphi)

    program Project2;

    {$APPTYPE CONSOLE}

    {$R *.res}

    uses
    System.SysUtils, System.DateUtils, FMX.Dialogs;

    Procedure Ingresar (var A: Integer);
    var
    Valido: Boolean;
    begin
    Repeat
    Write (‘Ingrese el anio (1800 a 2200): ‘);
    ReadLn (A);
    Valido := (A > 1799) and (A < 2201)
    Until Valido;
    WriteLn
    end;

    Procedure Procesar (const Mes, Anio: Integer; var n, i: Integer);

    function Zeller (d, m, a: word): byte;
    {
    La congruencia de Zeller es un algoritmo que permite obtener, a partir de una fecha,
    el día de la semana que le corresponde.
    Se atribuye su creación a Julius Christian Johannes Zeller, un sacerdote protestante
    alemán que vivió en el siglo XIX.

    Zeller observó que existía una dependencia entre las fechas del calendario gregoriano
    y el día de la semana que les correspondía.
    A raíz de esa observación, obtuvo (se dice que por tanteo), esta fórmula,
    en apariencia mágica, que lleva su nombre.
    }

    var
    e, f: word;

    begin
    if (m <= 2) then begin
    m := m + 10;
    a := a – 1;
    end else
    m := m – 2;
    e := a mod 100;
    f := a div 100;
    result := (700 + ((26 * m – 2) div 10) + d + e + e div 4 + f div 4 – 2 * f) mod 7
    end;

    begin
    i := Zeller (1, Mes, Anio);
    n := DaysInAMonth (Anio, Mes) //Función de delphi, devuelve la cantidad de días del mes sea año viciesto o no

    //No me extrañaría que delphi tenga ya en algún lado una función que devuelva
    //donde empieza el calendario…
    end;

    Procedure Mostrar (const Inicio, TotalDias, Mes, Anio: Integer);
    const
    M: array[1..12] of string = ('ENERO', 'FEBRERO', 'MARZO', 'ABRIL', 'MAYO', 'JUNIO',
    'JULIO', 'AGOSTO', 'SEPTIEMBRE', 'OCTUBRE', 'NOVIEMBRE', 'DICIEMBRE');
    var
    I, J, K, L: Integer;

    begin
    WriteLn (M[mes], ' del ', Anio);
    WriteLn;
    WriteLn (' D L M X J V S');
    WriteLn (' ——————————-');

    K := 1;
    L := 0;
    for I := 1 to 6 do begin
    for J := 1 to 7 do begin
    if (L TotalDias) then begin
    Write (‘ ‘);
    Inc (L)
    end else begin
    Write (K:5);
    inc (K)
    end
    end;
    WriteLn
    end
    end;

    var
    Mes, Anio, TDias, IniMes: Integer;
    Respuesta: Char;

    begin
    try
    repeat
    Ingresar (Anio);
    for Mes := 1 to 12 do begin
    Procesar (Mes, Anio, TDias, IniMes);
    Mostrar (IniMes, TDias, Mes, Anio);
    ReadLn
    end;

    WriteLn;
    Write (‘Otro anio? ‘);
    ReadLn (Respuesta);
    Respuesta := UpCase (Respuesta)
    until Respuesta ‘S’
    except
    on E: Exception do
    ShowMessage(E.ClassName + ‘: ‘ + E.Message)
    end
    end.

  13. Julio Cesar Romeo | 24 de enero de 2014 | 08:04

    Vótalo Thumb up 0

    Los valores de las tablas, exceptuando la última que es la más clara de entender, ¿de dónde salen? ¿por qué esos números?

  14. juanjo escribano | 24 de enero de 2014 | 09:19

    Vótalo Thumb up 0

    Hola Julio Cesar,

    las tablas se basan simple y llanamente en tomar un dia conocido y hacer calores módulo 7.

    A: Indica el dia de la semana del “0″ de Enero del comienzo de la centuria.
    B: Indica bisiestos que han pasado
    C: Corrige si la fecha es anterior al 1 de Marzo de un año bisiesto el apartado B
    D: Desplazamiento de cada 1 de mes respecto al origen módulo 7
    E: Autoexplicativo

  15. charlie | 26 de enero de 2014 | 22:41

    Vótalo Thumb up 0

    Juanjo Escribano, hay algo que no esta bien en tu razonamiento, sugiero lo vuelvas a razonar.
    si te fijas el ultimo parámetro es el dia del mes a calcular, sigue razonándolo y cuando lo tengas todo razonado vuelve a publicar

  16. Jose | 23 de febrero de 2014 | 00:04

    Vótalo Thumb up 0

    He conseguido memorizar el proceso y funciona, pero encontre un caso muy peculiar.
    Siguiendo con esta tecnica si yo quisiera saber que dia sera un 25 de Febrero de 2816, me sale Martes y en realidad sera Jueves. aqui lo puedes checar…. http://www.cuandoenelmundo.com/calendario/mexico/2816

    Que me puedes comentar???

  17. JJGJJG | 23 de febrero de 2014 | 05:18

    Vótalo Thumb up 0

    Jose, la secuencia para el valor de A debe ampliarse para fechas posteriores a 2299.

    Teniendo en cuenta que el -2 y el -4 son equivalentes a 5 y 3, módulo 7 quedaría así entre 1700 y 2999:

    +5, +3, +1, 0, +5, +3, +1, 0, +5, +3, +1, 0 y +5.

    (A partir de 3000, como este no será bisiesto esta secuencia varía pero es fácil de calcular).

    Entrando con A=0 para el intervalo 2800-2899 resulta que el 25 de febrero de 2816 resulta ser jueves.

    Que conste que extrapolando la secuencia restando una o dos unidades según que el inicio del intervalo sea o no bisiesto, como se propone en la cabecera también funciona, pero la que yo sugiero parece más estética porque todos los valores son positivos.

    La propuesta arriba quedaría así:

    +5, +3, +1, 0, -2, -4, -6, -7, -9, -11, -13, -14, -16, -18, -20, -21 y -23.

    Para el intervalo 2800-2899 queda A=-21, y -21 es congruente con 0 módulo 7 y el resultado sigue siendo jueves.

    Una curiosidad: dentro de cada milenio el calendario se repite cada 400 años. Es decir, el calendario de 2014 vale vpara 2414 y para 2814.

    Otra curiosidad: dentro de un cada siglo el calendario se repite cada 28 años. Es decir, el calendario de 2014 vale para 2042, para 2070 y para 2098. Y este año, al haber sido bisiesto el 2000, podríamos utilizar los de 1986 o de 1958 que tengamos viejos en casa.

  18. john j | 23 de marzo de 2014 | 07:46

    Vótalo Thumb up 0

    no me cuadra la fecha jun 28 de 1969, da cero, es decir domingo y reañmente fue un sabado A 1 B 17 C 0 D 3 E 28 igual 49 modulo 7 igual cero

  19. JJGJJG | 23 de marzo de 2014 | 12:04

    Vótalo Thumb up 0

    john, tu B es erróneo, se obtiene el correcto sumando los dos últimos dígitos (69) a su cuarta parte (17) y da 86. Con este valor sí sale sábado.

Escribe un comentario

Puedes utilizar código LaTeX para insertar fórmulas en los comentarios. Sólo tienes que escribir
[latex]código-latex-que-quieras-insertar[/latex]
o
$latex código-latex-que-quieras-insertar$.

Si tienes alguna duda sobre cómo escribir algún símbolo puede ayudarte la Wikipedia. Utiliza la Vista Previa antes de publicar tu comentario para asegurarte de que las fórmulas están correctamente escritas.