Blog alskare

.Net y lo que surja

Calculo de Semana Santa con C#

Posted by alskare en 05/04/2010

Hacía ya bastante tiempo que no tocaba el blog, así que ya va siendo hora de añadir algún que otro post. A ver si tengo tiempo estos días para poder hacer un par de entradas que tengo en mente, aunque el quehacer diario nos impide dedicarnos todo lo que queremos.

En esta ocasión le toca el turno a unos cálculos que he tenido que realizar para poder calcular ciertos días de la Semana Santa. Para documentarme, debo reconocer que tan sólo he echado mano de nuestra querida wikipedia (http://es.wikipedia.org/wiki/C%C3%A1lculo_de_la_fecha_de_Pascua#C.C3.A1lculo), así que ha sido bastante sencillo dicho cálculo. Como siempre, intento explicar un poco los pasos seguidos para lograr el fin.

A primera vista, los cálculos se ven sencillos, puesto que se trata de conseguir los residuos de una serie de divisiones. Quizás el único hándicap puede venir representado por la tabla de constantes que se muestra en la página de la Wikipedia. ¿Cómo lo solvento?. Pues, como siempre intento hacer, sin complicarme la vida, es decir, una estructura dentro de la clase que me permita almacenar los valores y un método que los cargue:

#region Constantes cálculo
private struct ParConstantes
{
    public int M { get; set; }
    public int N { get; set; }
}

private ParConstantes getPar(int anio)
{
    ParConstantes p = new ParConstantes();
    if (anio < 1583) { throw 
            new ArgumentOutOfRangeException("El año deberá ser superior a 1583"); }
    else if (anio < 1700) { p.M = 22; p.N = 2; }
    else if (anio < 1800) { p.M = 23; p.N = 3; }
    else if (anio < 1900) { p.M = 23; p.N = 4; }
    else if (anio < 2100) { p.M = 24; p.N = 5; }
    else if (anio < 2200) { p.M = 24; p.N = 6; }
    else if (anio < 2299) { p.M = 25; p.N = 0; }
    else { throw 
        new ArgumentOutOfRangeException("El año deberá ser inferior a 2299"); }
    return p;
}
#endregion

 

Así, una vez está solventado el problema de la tabla de las constantes, lo único que queda es el tema de los cálculos. En esta ocasión, dejo la clase completa, puesto que no tiene mayor complicación.

using System;


namespace jnSoftware.Calculos
{

    /// <summary>
    /// Cálculo de Semana Santa
    /// </summary>
    class SemanaSanta
    {
        private int a;
        private int b;
        private int c;
        private int d;
        private int e;
        private DateTime pascuaResurreccion;

        private int anio;


        /// <summary>
        /// Constructor de la clase
        /// </summary>
        /// <param name="anio">Entero que representa el año del que se quiere calcular la 
        /// semana santa.</param>
        /// <exception cref="ArgumentOutOfRangeException">Se produce cuando se intenta calcular
        /// la semana santa de un año no contemplado.</exception>
        public SemanaSanta(int anio)
        {
            try
            {
                this.anio = anio;
                calculaDomingoPascua();
            }
            catch { throw; }
        }


        /// <summary>
        /// Cálculo del domingo de Pascua o domingo de Resurrección.
        /// </summary>
        private void calculaDomingoPascua()
        {
            ParConstantes p = getPar(anio);
            a = anio % 19;
            b = anio % 4;
            c = anio % 7;
            d = (19 * a + p.M) % 30;
            e = (2 * b + 4 * c + 6 * d + p.N) % 7;

            if (d + e < 10)
            {
                pascuaResurreccion = new DateTime(anio, 3, d + e + 22);
            }
            else
            {
                pascuaResurreccion = new DateTime(anio, 4, d + e - 9);
            }

            // Excepciones
            if (pascuaResurreccion == new DateTime(anio, 4, 26))
                pascuaResurreccion = new DateTime(anio, 4, 19);

            if (pascuaResurreccion == new DateTime(anio, 4, 25) && d == 28 && e == 6 && a > 10)
                pascuaResurreccion = new DateTime(anio, 4, 18);
        }


        #region Constantes cálculo
        private struct ParConstantes
        {
            public int M { get; set; }
            public int N { get; set; }
        }

        private ParConstantes getPar(int anio)
        {
            ParConstantes p = new ParConstantes();
            if (anio < 1583) { throw 
                    new ArgumentOutOfRangeException("El año deberá ser superior a 1583"); }
            else if (anio < 1700) { p.M = 22; p.N = 2; }
            else if (anio < 1800) { p.M = 23; p.N = 3; }
            else if (anio < 1900) { p.M = 23; p.N = 4; }
            else if (anio < 2100) { p.M = 24; p.N = 5; }
            else if (anio < 2200) { p.M = 24; p.N = 6; }
            else if (anio < 2299) { p.M = 25; p.N = 0; }
            else { throw 
                new ArgumentOutOfRangeException("El año deberá ser inferior a 2299"); }
            return p;
        }
        #endregion


        #region Propiedades públicas

        public DateTime MiercolesCeniza
        {
            get { return SabadoSanto.AddDays(7 * -6 - 3 ); }
        }
        
        public DateTime ViernesDolores
        {
            get { return pascuaResurreccion.AddDays(-9); }
        }

        public DateTime DomingoRamos
        {
            get { return pascuaResurreccion.AddDays(-7); }
        }

        public DateTime JuevesSanto
        {
            get { return pascuaResurreccion.AddDays(-3); }
        }

        public DateTime ViernesSanto
        {
            get { return pascuaResurreccion.AddDays(-2); }
        }

        public DateTime SabadoSanto
        {
            get { return pascuaResurreccion.AddDays(-1); }
        }

        public DateTime DomingoResurreccion
        {
            get { return pascuaResurreccion; }
        }

        #endregion

    }
    
}

Tal como puede apreciarse, tan sólo se trata de calcular el Domingo de Resurrección ( o Domingo de Pascua) y, a partir de ahí, realizar la diferencia en días para obtener el resto.

No sé si me he dejado alguna otra fecha así que animo, como siempre ha hecho el lector de este blog, a completar, entre todos, las posibles fechas que puedan ser calculadas a partir de las fechas aquí calculadas.

2 comentarios to “Calculo de Semana Santa con C#”

  1. alskare said

    Pues la verdad es que no tengo ni idea. Imagino que para el año 2298 nos tocará volver a consultar la Wikipedia… ;-)

  2. Darneth said

    Sorry, pero…
    tengo una duda.
    Hay alguna forma de calcular las constantes M y N para el resto de los años hasta el fin de los tiempos??? o_o

Sorry, the comment form is closed at this time.

 
A %d blogueros les gusta esto: