Skip to content

Commit

Permalink
add specialdays sub-package to calculate public holidays and other sp…
Browse files Browse the repository at this point in the history
…ecial days
  • Loading branch information
SimonWaldherr committed Nov 4, 2023
1 parent 671d7fb commit a1397b8
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 0 deletions.
48 changes: 48 additions & 0 deletions specialdays/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package specialdays_test

import (
"fmt"
"sort"
"simonwaldherr.de/go/golibs/specialdays"
)

func ExampleGetSpecialDays() {
days := specialdays.GetSpecialDays(2019)

keys := make([]string, 0, len(days))

for k := range days{
keys = append(keys, k)
}
sort.Strings(keys)

for _, k := range keys {
fmt.Printf("%s: %s\n", k, days[k].Format("2006-01-02"))
}

// Output:
// 1. Weihnachtstag: 2019-12-25
// 2. Weihnachtstag: 2019-12-26
// Allerheiligen: 2019-11-01
// Buß- und Bettag: 2019-11-20
// Christi Himmelfahrt: 2019-05-30
// Fronleichnam: 2019-06-20
// Halloween: 2019-10-31
// Heiligabend: 2019-12-24
// Heilige Drei Könige: 2019-01-06
// Karfreitag: 2019-04-19
// Karnevalsbeginn: 2019-11-11
// Mariä Himmelfahrt: 2019-08-15
// Muttertag: 2019-05-12
// Neujahrstag: 2019-01-01
// Nikolaustag: 2019-12-06
// Ostermontag: 2019-04-22
// Ostersonntag: 2019-04-21
// Pfingstmontag: 2019-06-10
// Pfingstsonntag: 2019-06-09
// Silvester: 2019-12-31
// Tag der Arbeit: 2019-05-01
// Tag der Deutschen Einheit: 2019-10-03
// Valentinstag: 2019-02-14
// erster Advent: 2019-12-01
}
108 changes: 108 additions & 0 deletions specialdays/specialdays.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package specialdays

import (
"time"
)

// CalculateEasterSunday berechnet den Ostersonntag für ein gegebenes Jahr.
func CalculateEasterSunday(year int) time.Time {
a := year % 19
b := year / 100
c := year % 100
d := b / 4
e := b % 4
f := (b + 8) / 25
g := (b - f + 1) / 3
h := (19*a + b - d - g + 15) % 30
i := c / 4
k := c % 4
l := (32 + 2*e + 2*i - h - k) % 7
m := (a + 11*h + 22*l) / 451
month := (h + l - 7*m + 114) / 31
day := ((h + l - 7*m + 114) % 31) + 1
return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
}

// CalculateMothersDay berechnet den Muttertag für ein gegebenes Jahr (2. Sonntag im Mai).
func CalculateMothersDay(year int) time.Time {
// Der 1. Mai des Jahres
mayFirst := time.Date(year, time.May, 1, 0, 0, 0, 0, time.UTC)

// Wochentag des 1. Mai berechnen
weekday := mayFirst.Weekday()

// Den ersten Sonntag im Mai finden
daysUntilSunday := (7 - int(weekday)) % 7
firstSunday := mayFirst.AddDate(0, 0, daysUntilSunday)

// Den zweiten Sonntag im Mai berechnen
secondSunday := firstSunday.AddDate(0, 0, 7)

return secondSunday
}

// CalculateFronleichnam berechnet Fronleichnam für ein gegebenes Jahr (60 Tage nach Ostern).
func CalculateFronleichnam(year int) time.Time {
easterSunday := CalculateEasterSunday(year)
return easterSunday.AddDate(0, 0, 60)
}

// CalculateFirstAdvent berechnet den ersten Advent für ein gegebenes Jahr.
func CalculateFirstAdvent(year int) time.Time {
// Der erste Advent ist der Sonntag zwischen dem 27. November und dem 3. Dezember.
firstAdvent := time.Date(year, time.December, 3, 0, 0, 0, 0, time.UTC)
for firstAdvent.Weekday() != time.Sunday {
firstAdvent = firstAdvent.AddDate(0, 0, -1)
}
return firstAdvent
}

// CalculateBussUndBettag berechnet den Buß- und Bettag für ein gegebenes Jahr.
func CalculateBussUndBettag(year int) time.Time {
// Der Buß- und Bettag ist der Mittwoch vor dem ersten Advent.
firstAdvent := CalculateFirstAdvent(year)
bussUndBettag := firstAdvent.AddDate(0, 0, -11)

return bussUndBettag
}

// GetSpecialDays gibt eine Map mit allen besonderen Tagen für ein gegebenes Jahr zurück.
func GetSpecialDays(year int) map[string]time.Time {
specialDays := make(map[string]time.Time)

// Statische Feiertage und besondere Tage
specialDays["Neujahrstag"] = time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC)
specialDays["Tag der Arbeit"] = time.Date(year, 5, 1, 0, 0, 0, 0, time.UTC)
specialDays["Tag der Deutschen Einheit"] = time.Date(year, 10, 3, 0, 0, 0, 0, time.UTC)
specialDays["Nikolaustag"] = time.Date(year, time.December, 6, 0, 0, 0, 0, time.UTC)
specialDays["Heiligabend"] = time.Date(year, 12, 24, 0, 0, 0, 0, time.UTC)
specialDays["1. Weihnachtstag"] = time.Date(year, 12, 25, 0, 0, 0, 0, time.UTC)
specialDays["2. Weihnachtstag"] = time.Date(year, 12, 26, 0, 0, 0, 0, time.UTC)
specialDays["Silvester"] = time.Date(year, 12, 31, 0, 0, 0, 0, time.UTC)

// Bewegliche Feiertage
easterSunday := CalculateEasterSunday(year)
specialDays["Karfreitag"] = easterSunday.AddDate(0, 0, -2)
specialDays["Ostersonntag"] = easterSunday
specialDays["Ostermontag"] = easterSunday.AddDate(0, 0, 1)
specialDays["Christi Himmelfahrt"] = easterSunday.AddDate(0, 0, 39)
specialDays["Pfingstsonntag"] = easterSunday.AddDate(0, 0, 49)
specialDays["Pfingstmontag"] = easterSunday.AddDate(0, 0, 50)
specialDays["Fronleichnam"] = easterSunday.AddDate(0, 0, 60)
specialDays["erster Advent"] = CalculateFirstAdvent(year)

// Andere besondere Tage
specialDays["Valentinstag"] = time.Date(year, 2, 14, 0, 0, 0, 0, time.UTC)
specialDays["Muttertag"] = CalculateMothersDay(year)
specialDays["Halloween"] = time.Date(year, 10, 31, 0, 0, 0, 0, time.UTC)
specialDays["Karnevalsbeginn"] = time.Date(year, 11, 11, 0, 0, 0, 0, time.UTC)

// Weitere Feiertage
specialDays["Heilige Drei Könige"] = time.Date(year, time.January, 6, 0, 0, 0, 0, time.UTC)
specialDays["Fronleichnam"] = CalculateFronleichnam(year)
specialDays["Mariä Himmelfahrt"] = time.Date(year, time.August, 15, 0, 0, 0, 0, time.UTC)
specialDays["Allerheiligen"] = time.Date(year, time.November, 1, 0, 0, 0, 0, time.UTC)
specialDays["Buß- und Bettag"] = CalculateBussUndBettag(year)

return specialDays
}
75 changes: 75 additions & 0 deletions specialdays/specialdays_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package specialdays

import (
"testing"
"time"
)

// TestCalculateEasterSunday testet die Berechnung des Ostersonntags für verschiedene Jahre.
func TestCalculateEasterSunday(t *testing.T) {
testCases := []struct {
year int
expected time.Time
}{
{2020, time.Date(2020, time.April, 12, 0, 0, 0, 0, time.UTC)},
{2024, time.Date(2024, time.March, 31, 0, 0, 0, 0, time.UTC)},
{2025, time.Date(2025, time.April, 20, 0, 0, 0, 0, time.UTC)},
{2026, time.Date(2026, time.April, 5, 0, 0, 0, 0, time.UTC)},
// Weitere Testfälle...
}

for _, tc := range testCases {
calculatedDate := CalculateEasterSunday(tc.year)
if !tc.expected.Equal(calculatedDate) {
t.Errorf("Expected Easter Sunday of %d to be %v, but got %v", tc.year, tc.expected, calculatedDate)
}
}
}

// TestCalculateMothersDay testet die Berechnung des Muttertags für verschiedene Jahre.
func TestCalculateMothersDay(t *testing.T) {
testCases := []struct {
year int
expected time.Time
}{
{2020, time.Date(2020, time.May, 10, 0, 0, 0, 0, time.UTC)},
{2024, time.Date(2024, time.May, 12, 0, 0, 0, 0, time.UTC)},
{2025, time.Date(2025, time.May, 11, 0, 0, 0, 0, time.UTC)},
{2026, time.Date(2026, time.May, 10, 0, 0, 0, 0, time.UTC)},
// Weitere Testfälle...
}

for _, tc := range testCases {
calculatedDate := CalculateMothersDay(tc.year)
if !tc.expected.Equal(calculatedDate) {
t.Errorf("Expected Mothers Day of %d to be %v, but got %v", tc.year, tc.expected, calculatedDate)
}
}
}

// TestGetSpecialDays testet die Map der besonderen Tage für ein bestimmtes Jahr.
func TestGetSpecialDays(t *testing.T) {
year := 2024
specialDays := GetSpecialDays(year)

testCases := []struct {
name string
expected time.Time
}{
{"Neujahrstag", time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC)},
{"Tag der Arbeit", time.Date(year, time.May, 1, 0, 0, 0, 0, time.UTC)},
{"Tag der Deutschen Einheit", time.Date(year, time.October, 3, 0, 0, 0, 0, time.UTC)},
{"Heiligabend", time.Date(year, time.December, 24, 0, 0, 0, 0, time.UTC)},
// Weitere Testfälle...
}

for _, tc := range testCases {
if date, ok := specialDays[tc.name]; ok {
if !tc.expected.Equal(date) {
t.Errorf("Expected %s to be %v, but got %v", tc.name, tc.expected, date)
}
} else {
t.Errorf("Expected %s to be in special days map", tc.name)
}
}
}

0 comments on commit a1397b8

Please sign in to comment.