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()
    }
}






COBOL:        identification division.
       program-id. Easter.
 
       environment division.
       configuration section.
       repository.
           function date-of-integer intrinsic
           function integer-of-date intrinsic
           function mod intrinsic.
 
       data division.
       working-storage section.
       77  days                   pic 9(2).
       77  a                      pic 9(2).  
       77  b                      pic 9(2).  
       77  c                      pic 9(2).  
       77  d                      pic 9(2).  
       77  e                      pic 9(2).  
       77  f                      pic 9(2).  
       77  g                      pic 9(2).  
       77  h                      pic 9(2).  
       77  i                      pic 9(2).  
       77  k                      pic 9(2).  
       77  l                      pic 9(2).  
       77  m                      pic 9(2).  
       77  week-day               pic 9(1).
       77  numerator              pic 9(4).
       77  integer-date           pic 9(18).
       
       01  month-tab              value "JanFebMarAprMayJunJulAugSepOctNovDec".
           05 month-abreviated    pic x(3) occurs 12.
           
       01  week-day-tab           value "SunMonTueWedThuFriSat".
           05 week-day-abreviated pic x(3) occurs 7.
       
       01  easter-date            pic 9(8).
       01  filler redefines easter-date.
           05 easter-year         pic 9(4).
           05 easter-month        pic 9(2).
           05 easter-day          pic 9(2).

       01  holiday-date           pic 9(8).
       01  filler redefines holiday-date.
           05 holiday-year        pic 9(4).
           05 holiday-month       pic 9(2).
           05 holiday-day         pic 9(2).

       01  edt-date.
           05 edt-week-day        pic x(3).
           05 filler              pic x value space.
           05 edt-day             pic z(2).
           05 filler              pic x value space.
           05 edt-month           pic x(3).

       procedure division.
       main.
           display "Christian holidays, related to Easter, for each centennial from 1700 to 2100 CE:"
           perform varying easter-year from 1700 by 100 until easter-year > 2100
              perform output-holydays
           end-perform
           display " "

           display "Christian holidays, related to Easter, for years from 2010 to 2020 CE:"
           perform varying easter-year from 2010 by 1 until easter-year > 2020
              perform output-holydays
           end-perform
           display " "

           stop run
           .
       output-holydays.
           display easter-year " " no advancing
           perform calculate-easter

           move 0 to days
           perform add-days
           display " Easter: " edt-date no advancing

           move 39 to days
           perform add-days
           display " Ascension: " edt-date no advancing

           move 49 to days
           perform add-days
           display " Pentecost: " edt-date no advancing

           move 56 to days
           perform add-days
           display " Trinity: " edt-date no advancing

           move 60 to days
           perform add-days
           display " Corpus: " edt-date 
           .
       calculate-easter.
           compute a = mod(easter-year, 19)
           compute b = easter-year / 100
           compute c = mod(easter-year, 100)
           compute d = b / 4
           compute e = mod(b, 4)
           compute f = (b + 8) / 25
           compute g = (b - f + 1) / 3
           compute h = mod((19 * a + b - d - g + 15), 30)
           compute i = c / 4
           compute k = mod(c, 4)
           compute l = mod((32 + 2 * e + 2 * i - h - k), 7)
           compute m = (a + 11 * h + 22 * l) / 451
           compute numerator = h + l - 7 * m + 114
           compute easter-month = numerator / 31
           compute easter-day = mod(numerator, 31) + 1
           .
       add-days.
           if days = 0
              move easter-date to holiday-date
              move 1 to week-day
           else
              compute holiday-date = date-of-integer(integer-of-date(easter-date) + days)
              compute week-day = mod(integer-of-date(easter-date) + days, 7) + 1
           end-if
           move week-day-abreviated(week-day) to edt-week-day
           move month-abreviated(holiday-month) to edt-month
           move holiday-day to edt-day
           .