Skip to content

Instantly share code, notes, and snippets.

@marvi
Created August 24, 2011 15:00
Show Gist options
  • Save marvi/1168255 to your computer and use it in GitHub Desktop.
Save marvi/1168255 to your computer and use it in GitHub Desktop.
Uträkning av kyrkoåret
package lectio.cal;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.joda.time.DateTimeConstants;
import org.joda.time.LocalDate;
/**
* Represents a Liturgical year in the Church of Sweden tradition.<br>
*
* Note that calendar year and liturgical year doesn't align. The liturgical
* year starts first Sunday of Advent the previous calendar year. <br>
* The year used in this class is the year of the Easter Sunday of this liturgical year.
* I.e. the liturgical year 2013 starts 2012-12-02.<br>
*
* Inspiration from http://www.lysator.liu.se/alma/alma.cgi
*
* http://www.svenskakyrkan.se/tcrot/kyrkoordningen/filer/KO-kap-28.pdf
*
* @author marvi
*/
public class LiturgicalYear implements Serializable {
/**
* The year this liturgical years Easter Sunday occurs.
*/
private final int year;
private LocalDate easterDay;
private int readingCycle;
private SortedMap<LocalDate, Day> daysOfYear = new TreeMap<LocalDate, Day>();
private final String[] swedishCounting = new String[] {"Första", "Andra", "Tredje", "Fjärde", "Femte",
"Sjätte", "Sjunde", "Åttonde", "Nionde", "Tionde", "Elfte", "Tolfte", "Trettonde",
"Fjortonde", "Femtonde", "Sextonde", "Sjuttonde", "Artonde", "Nittonde", "Tjugonde",
"Tjugoförsta", "Tjugoandra", "Tjugotredje", "Tjugofjärde", "Tjugofemte", "Tjugosjätte",
"Tjugosjunde"};
/**
*
* @param year The year to use.
*/
public LiturgicalYear(int year) {
this.year = year;
this.readingCycle = this.getReadingCycle();
easterDay = CalculateEaster.forYear(year);
populateDaysOfYear();
}
/**
* Default constructor. Uses current year.
*/
public LiturgicalYear() {
this.year = new LocalDate(new Date()).getYear();
easterDay = CalculateEaster.forYear(year);
populateDaysOfYear();
}
/**
* @return the year
*/
public int getYear() {
return year;
}
/**
*
* @return the reading cycle for this liturgical year (1-3)
*/
public final int getReadingCycle() {
return getReadingCycle(year);
}
public final int getEasterSeries() {
return getEasterSeries(year);
}
public static int getReadingCycle(int year) {
if (year < 1986) {
return 0;
} else if (year < 2003) {
return (year - 1986) % 3 + 1;
}
return (year - 2003) % 3 + 1;
}
public static int getEasterSeries(int year) {
if (year < 2004) {
return 0;
}
return (year - 2002) % 4 + 1;
}
/**
* Maps the holidays to actual dates for this year.
*/
private void populateDaysOfYear() {
// Fixed days
daysOfYear.put(new LocalDate(year - 1, 12, 24), new Day("Julnatten", new LocalDate(year - 1, 12, 24), readingCycle));
daysOfYear.put(new LocalDate(year - 1, 12, 25), new Day("Juldagen", new LocalDate(year - 1, 12, 25), readingCycle));
daysOfYear.put(new LocalDate(year - 1, 12, 26), new Day("Annandag jul", new LocalDate(year - 1, 12, 26), readingCycle));
daysOfYear.put(new LocalDate(year - 1, 12, 31), new Day("Nyårsafton", new LocalDate(year - 1, 12, 31), readingCycle));
daysOfYear.put(new LocalDate(year, 1, 1), new Day("Nyårsdagen", new LocalDate(year, 1, 1), readingCycle));
daysOfYear.put(new LocalDate(year, 1, 5), new Day("Trettondagsafton", new LocalDate(year, 1, 5), readingCycle));
daysOfYear.put(new LocalDate(year, 1, 6), new Day("Trettondedag jul", new LocalDate(year, 1, 6), readingCycle));
// Söndagen efter jul infaller inte varje år.
LocalDate sej = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate((year - 1), 12, 26));
if (sej.isBefore(new LocalDate(year, 1, 1))) {
daysOfYear.put(sej, new Day("Söndagen efter jul", sej, readingCycle));
}
// "Söndagen efter nyår" infaller inte varje år.
if (sundayAfterNewYear() != null) {
daysOfYear.put(sundayAfterNewYear(), new Day("Söndagen efter nyår", sundayAfterNewYear(), readingCycle));
}
// Kyndelsmässodagen (flyttas tillbaka en vecka om den infaller på fastlagssöndagen
LocalDate kynd = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate(year, 2, 1));
if (kynd.equals(easterDay.minusDays(49))) {
kynd = kynd.minusDays(7);
}
daysOfYear.put(kynd, new Day("Kyndelsmässodagen", kynd, readingCycle));
// Söndagar efter trettondedagen
int add = 0;
int i = 0;
while (i < 8) {
LocalDate d = firstAfterEpifania().plusDays(add);
if (!d.isEqual(kynd) && d.isBefore(easterDay.minusDays(63))) {
String prefix = swedishCounting[i];
daysOfYear.put(d, new Day(prefix + " söndagen efter trettondedagen", d, readingCycle));
} else if (d.isEqual(easterDay.minusDays(63))
|| d.isAfter(easterDay.minusDays(63))) {
i = 8;
}
add = add + 7;
i++;
}
// Jungfru Marie bebådelsedag
LocalDate jmb = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate(year, 3, 21));
if (jmb.isAfter(easterDay.minusDays(8))) {
jmb = easterDay.minusDays(14);
}
daysOfYear.put(jmb, new Day("Jungfru Marie bebådelsedag", jmb, readingCycle));
//System.out.println(daysOfYear.get(jmb) + " " + easterDay.minusDays(42));
if (!kynd.isEqual(easterDay.minusDays(63))) {
daysOfYear.put(easterDay.minusDays(63), new Day("Septuagesima", easterDay.minusDays(63), readingCycle));
}
if (!kynd.isEqual(easterDay.minusDays(56))) {
daysOfYear.put(easterDay.minusDays(56), new Day("Sexagesima", easterDay.minusDays(56), readingCycle));
}
daysOfYear.put(easterDay.minusDays(49), new Day("Fastlagssöndagen", easterDay.minusDays(49), readingCycle));
daysOfYear.put(easterDay.minusDays(46), new Day("Askonsdagen", easterDay.minusDays(46), readingCycle));
if (!jmb.isEqual(easterDay.minusDays(42))) {
daysOfYear.put(easterDay.minusDays(42), new Day("Första söndagen i fastan", easterDay.minusDays(42), readingCycle));
}
if (!jmb.isEqual(easterDay.minusDays(35))) {
daysOfYear.put(easterDay.minusDays(35), new Day("Andra söndagen i fastan", easterDay.minusDays(35), readingCycle));
}
if (!jmb.isEqual(easterDay.minusDays(28))) {
daysOfYear.put(easterDay.minusDays(28), new Day("Tredje söndagen i fastan", easterDay.minusDays(28), readingCycle));
}
if (!jmb.isEqual(easterDay.minusDays(21))) {
daysOfYear.put(easterDay.minusDays(21), new Day("Midfastosöndagen", easterDay.minusDays(21), readingCycle));
}
if (!jmb.isEqual(easterDay.minusDays(14))) {
daysOfYear.put(easterDay.minusDays(14), new Day("Femte söndagen i fastan", easterDay.minusDays(14), readingCycle));
}
// Utgår från påsken
daysOfYear.put(easterDay, new Day("Påskdagen", easterDay, readingCycle));
daysOfYear.put(easterDay.minusDays(1), new Day("Påsknatten", easterDay.minusDays(1), readingCycle));
daysOfYear.put(easterDay.minusDays(2), new Day("Långfredagen", easterDay.minusDays(2), readingCycle));
daysOfYear.put(easterDay.minusDays(3), new Day("Skärtorsdagen", easterDay.minusDays(3), readingCycle));
daysOfYear.put(easterDay.minusDays(4), new Day("Onsdag i Stilla veckan", easterDay.minusDays(4), readingCycle));
daysOfYear.put(easterDay.minusDays(5), new Day("Tisdag i Stilla veckan", easterDay.minusDays(5), readingCycle));
daysOfYear.put(easterDay.minusDays(6), new Day("Måndag i Stilla veckan", easterDay.minusDays(6), readingCycle));
daysOfYear.put(easterDay.minusDays(7), new Day("Palmsöndagen", easterDay.minusDays(7), readingCycle));
daysOfYear.put(easterDay.plusDays(1), new Day("Annandag påsk", easterDay.plusDays(1), readingCycle));
daysOfYear.put(easterDay.plusDays(7), new Day("Andra söndagen i påsktiden", easterDay.plusDays(7), readingCycle));
daysOfYear.put(easterDay.plusDays(14), new Day("Tredje söndagen i påsktiden", easterDay.plusDays(14), readingCycle));
daysOfYear.put(easterDay.plusDays(21), new Day("Fjärde söndagen i påsktiden", easterDay.plusDays(21), readingCycle));
daysOfYear.put(easterDay.plusDays(28), new Day("Femte söndagen i påsktiden", easterDay.plusDays(28), readingCycle));
daysOfYear.put(easterDay.plusDays(35), new Day("Bönsöndagen", easterDay.plusDays(35), readingCycle));
daysOfYear.put(easterDay.plusDays(39), new Day("Kristi himmelsfärds dag", easterDay.plusDays(39), readingCycle));
daysOfYear.put(easterDay.plusDays(42), new Day("Söndagen före pingst", easterDay.plusDays(42), readingCycle));
daysOfYear.put(easterDay.plusDays(49), new Day("Pingstdagen", easterDay.plusDays(49), readingCycle));
daysOfYear.put(easterDay.plusDays(50), new Day("Annandag pingst", easterDay.plusDays(50), readingCycle));
daysOfYear.put(easterDay.plusDays(56), new Day("Heliga trefaldighets dag", easterDay.plusDays(56), readingCycle));
// Midsommardagen
LocalDate msd = nextWeekdayOfType(DateTimeConstants.SATURDAY, new LocalDate(year, 6, 19));
daysOfYear.put(msd, new Day("Midsommardagen", msd, readingCycle));
// Alla helons dag (behövs för att lägga ut trefaldighetstiden)
LocalDate ahd = nextWeekdayOfType(DateTimeConstants.SATURDAY, new LocalDate(year, 10, 30));
daysOfYear.put(ahd, new Day("Alla helgons dag", ahd, readingCycle));
daysOfYear.put(ahd.plusDays(1), new Day("Söndagen efter alla helgons dag", ahd.plusDays(1), readingCycle));
// Advent och kyrkoårets slut
LocalDate firstAdv = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate((year - 1), 11, 26));
daysOfYear.put(firstAdv, new Day("Första söndagen i advent", firstAdv, readingCycle));
daysOfYear.put(firstAdv.plusDays(7), new Day("Andra söndagen i advent", firstAdv.plusDays(7), readingCycle));
daysOfYear.put(firstAdv.plusDays(14), new Day("Tredje söndagen i advent", firstAdv.plusDays(14), readingCycle));
daysOfYear.put(firstAdv.plusDays(21), new Day("Fjärde söndagen i advent", firstAdv.plusDays(21), readingCycle));
// Kalenderårsadvent (för att räkna ut Domsöndag
LocalDate calFirstAdv = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate((year), 11, 26));
daysOfYear.put(calFirstAdv.minusDays(7), new Day("Domsöndagen", calFirstAdv.minusDays(7), readingCycle));
daysOfYear.put(calFirstAdv.minusDays(14), new Day("Söndagen före domsöndagen", calFirstAdv.minusDays(7), readingCycle));
// Trefaldighetssöndagarna
// Söndagar efter trettondedagen
LocalDate firstAfterTre = easterDay.plusDays(63);
add = 0;
i = 0;
while (i < 27) {
LocalDate setre = firstAfterTre.plusDays(add);
add = add + 7;
if (setre.isEqual(ahd.plusDays(1))) {
i++;
continue;
}
if (setre.isAfter(calFirstAdv.minusDays(15))) {
break;
}
String etreName = swedishCounting[i];
switch (i) {
case 4:
daysOfYear.put(setre, new Day("Apostladagen", setre, readingCycle));
break;
case 6:
daysOfYear.put(setre, new Day("Kristi förklarings dag", setre, readingCycle));
break;
default:
daysOfYear.put(setre, new Day(etreName + " söndagen efter trefaldighet", setre, readingCycle));
break;
}
i++;
}
// Johannes döparens dag
daysOfYear.put(msd.plusDays(1), new Day("Den helige Johannes Döparens dag", msd.plusDays(1), readingCycle));
// Den helige Mikaels dag
LocalDate hmd = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate(year, 9, 28));
daysOfYear.put(hmd, new Day("Den helige Mikaels dag", hmd, readingCycle));
// Tacksägelsedagen
LocalDate tsd = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate(year, 9, 30));
tsd = nextWeekdayOfType(DateTimeConstants.SUNDAY, tsd);
daysOfYear.put(tsd, new Day("Tacksägelsedagen", tsd, readingCycle));
}
private LocalDate sundayAfterNewYear() {
LocalDate candidate = nextWeekdayOfType(DateTimeConstants.SUNDAY, new LocalDate(year, 1, 1));
if (candidate.getDayOfMonth() < 6) {
return candidate;
}
return null;
}
private LocalDate firstAfterEpifania() {
LocalDate ep = new LocalDate(year, 1, 6);
return nextWeekdayOfType(DateTimeConstants.SUNDAY, ep);
}
/**
*
* @param wd The day of week
* @param date The date to start from
* @return The next date with this weekday
*/
protected static LocalDate nextWeekdayOfType(int wd, LocalDate date) {
if (date.getDayOfWeek() < wd) {
date = date.withDayOfWeek(wd);
} else {
date = date.plusWeeks(1).withDayOfWeek(wd);
}
return date;
}
/**
* @return a map with a date as key and the Day as value.
*/
public Map<LocalDate, Day> getDaysOfYear() {
return daysOfYear;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("LiturgicalYear{ year=");
sb.append(year);
sb.append(" ");
Set<LocalDate> days = daysOfYear.keySet();
for (LocalDate ld : days) {
sb.append(daysOfYear.get(ld).toString());
sb.append(" \n ");
}
sb.append(" }");
return sb.toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment