Easter date for a given year (golang)

vegaseat 0 Tallied Votes 952 Views Share

Some folks go on vacation around the Easter holidays, so it would be nice to know when Easter happens in the years ahead. I had this as a Python snippet in my "oldies, but goodies" file and translated it to Go. It was actually quite easy in this case, and a good IDE like LiteIDE helped a lot.

// easter_date2.go
//
// Easter date for a given year in the Gregorian calendar
// (1583 and onward) using the Gauss Algorithm
//
// fairly straight translation from one of my Python snippets
//
// tested with Go version 1.4.2   by vegaseat  2may2015

package main

import "fmt"

// Gauss algorithm to calculate the date of Easter in a given year
// returns day, month, year as integers
func getEaster2(year int) (int, int, int) {
	// don't go below start of Gregorian calendar
	if year < 1583 {
		year = 1583
	}
	// for type (by inference) and value assignment use :=
	// shorthand for   var month int = 3
	month := 3
	// determine the Golden number
	golden := (year % 19) + 1
	// determine the century number
	century := year/100 + 1
	// correct for the years that are not leap years
	xx := (3*century)/4 - 12
	// moon correction
	yy := (8*century+5)/25 - 5
	// find Sunday
	zz := (5*year)/4 - xx - 10
	// determine epact
	// age of moon on January 1st of that year
	// (follows a cycle of 19 years)
	ee := (11*golden + 20 + yy - xx) % 30
	if ee == 24 {
		ee += 1
	}
	if (ee == 25) && (golden > 11) {
		ee += 1
	}
	// get the full moon
	moon := 44 - ee
	if moon < 21 {
		moon += 30
	}
	// up to Sunday
	day := (moon + 7) - ((zz + moon) % 7)
	// possibly up a month in easter_date
	if day > 31 {
		day -= 31
		month = 4
	}
	return day, month, year
}

func main() {
	fmt.Println("Easter date of a given year:")

	for jahr := 2011; jahr <= 2018; jahr++ {
		day, month, year := getEaster2(jahr)
		fmt.Printf("Easter %d is on %v/%v/%v\n",
			year, month, day, year)
	}
}

/*
Easter date of a given year:
Easter 2011 is on 4/24/2011
Easter 2012 is on 4/8/2012
Easter 2013 is on 3/31/2013
Easter 2014 is on 4/20/2014
Easter 2015 is on 4/5/2015
Easter 2016 is on 3/27/2016
Easter 2017 is on 4/16/2017
Easter 2018 is on 4/1/2018
*/
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Here is another version using Butcher's algorithm ...

// easter_date.go
//
// Easter date for any year in the Gregorian calendar (1583 and onward)
// modified Butcher's Algorithm
//
// tested with Go version 1.4.2   by vegaseat  3may2015

package main

import (
    "fmt"
    "time"
)

type Easter struct {
    time.Time
}

func getEaster(y int) Easter {
    // don't go below start of Gregorian calendar
    if y < 1583 {
        y = 1583
    }
    c := y / 100
    n := y % 19
    i := (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 - (y+y/4+i+2-c+c/4)%7
    // month (1 - 12)
    m := 3 + (l+40)/44
    // day
    d := l + 28 - 31*(m/4)
    // convert to time.Date() format
    date := Easter{time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC)}
    return date
}

func main() {
    fmt.Println("Easter date of a given year:")

    for year := 2011; year <= 2018; year++ {
        tm := getEaster(year)
        fmt.Printf("Easter %d is on %v %v, %v\n",
            year, tm.Month(), tm.Day(), tm.Year())
    }

}

/*
Easter date of a given year:
Easter 2011 is on April 24, 2011
Easter 2012 is on April 8, 2012
Easter 2013 is on March 31, 2013
Easter 2014 is on April 20, 2014
Easter 2015 is on April 5, 2015
Easter 2016 is on March 27, 2016
Easter 2017 is on April 16, 2017
Easter 2018 is on April 1, 2018
*/
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.