Task: Holidays related to Easter




Go: package main

import (
    "fmt"
    "time"
)

type holiday struct {
    time.Time
}

func easter(y int) holiday {
    c := y / 100
    n := mod(y, 19)
    i := mod(c-c/4-(c-(c-17)/25)/3+19*n+15, 30)
    i -= (i / 28) * (1 - (i/28)*(29/(i+1))*((21-n)/11))
    l := i - mod(y+y/4+i+2-c+c/4, 7)
    m := 3 + (l+40)/44
    d := l + 28 - 31*(m/4)
    return holiday{time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC)}
}

func mod(a, n int) int {
    r := a % n
    if r < 0 {
        return r + n
    }
    return r
}

func (h holiday) addDays(d int) holiday {
    return holiday{h.Add(time.Duration(d) * 24 * time.Hour)}
}

type easterRelated struct {
    easter, ascension, pentecost, trinity, corpusChristi holiday
}

func newEasterRelated(y int) (er easterRelated) {
    er.easter = easter(y)
    er.ascension = er.easter.addDays(39)
    er.pentecost = er.ascension.addDays(10)
    er.trinity = er.pentecost.addDays(7)
    er.corpusChristi = er.trinity.addDays(4)
    return
}

func (er easterRelated) print() {
    const wdmdm = ": Mon _2 Jan"
    fmt.Printf("%4d %s, %s, %s, %s, %s\n",
        er.easter.Year(),
        er.easter.Format("Easter"+wdmdm),
        er.ascension.Format("Ascension"+wdmdm),
        er.pentecost.Format("Pentecost"+wdmdm),
        er.trinity.Format("Trinity"+wdmdm),
        er.corpusChristi.Format("Corpus"+wdmdm))
}

func main() {
    fmt.Println("Christian holidays, related to Easter, " +
        "for each centennial from 400 to 2100 CE:")
    for y := 400; y <= 2100; y += 100 {
        newEasterRelated(y).print()
    }
    fmt.Println("\nChristian holidays, related to Easter, " +
        "for years from 2010 to 2020 CE:")
    for y := 2010; y <= 2020; y++ {
        newEasterRelated(y).print()
    }
}








Ada: with Ada.Calendar.Arithmetic;
with Ada.Calendar.Formatting;
with Ada.Text_IO;

procedure Main is
   use Ada.Calendar;
   use Arithmetic;

   function Get_Easter (Year : Year_Number) return Time is
      A : Integer := Year mod 19;
      B : Integer := Year / 100;
      C : Integer := Year mod 100;
      D : Integer := B / 4;
      E : Integer := B mod 4;
      F : Integer := (B + 8) / 25;
      G : Integer := (B - F + 1) / 3;
      H : Integer := (19 * A + B - D - G + 15) mod 30;
      I : Integer := C / 4;
      K : Integer := C mod 4;
      L : Integer := (32 + 2 * E + 2 * I - H - K) mod 7;
      M : Integer := (A + 11 * H + 22 * L) / 451;
      N : Integer := H + L - 7 * M + 114;
   begin
      return Time_Of (Year, N / 31, N mod 31 + 1, 43200.0);
   end Get_Easter;

   procedure Print_Easter (Year : Year_Number) is
      Days_To_Ascension : constant Day_Count := 39;
      Days_To_Pentecost : constant Day_Count := 49;
      Days_To_Trinity   : constant Day_Count := 56;
      Days_To_Corpus    : constant Day_Count := 60;
      Easter : Time := Get_Easter (Year);
   begin
      Ada.Text_IO.Put (Integer'Image (Year));
      Ada.Text_IO.Put (": Easter: " &
                       Formatting.Image (Easter) (6 .. 10));
      Ada.Text_IO.Put (", Ascension: " &
                       Formatting.Image (Easter + Days_To_Ascension) (6 .. 10));
      Ada.Text_IO.Put (", Pentecost: " &
                       Formatting.Image (Easter + Days_To_Pentecost) (6 .. 10));
      Ada.Text_IO.Put (", Trinity: " &
                       Formatting.Image (Easter + Days_To_Trinity) (6 .. 10));
      Ada.Text_IO.Put_Line (", Corpus: " &
                       Formatting.Image (Easter + Days_To_Corpus) (6 .. 10));
   end Print_Easter;
begin
   Ada.Text_IO.Put_Line
     ("Christian holidays, related to Easter, for years from 2010 to 2020 CE:");
   for I in 2010 .. 2020 loop
      Print_Easter (I);
   end loop;
end Main;