3

I have created the following code (which works) to print something different based on the weeks of a specified month:

<script language="javascript">
<!--
var advent;
mytime=new Date();
mymonth=mytime.getMonth()+1;
mydate=mytime.getDate();
if (mymonth==12 && (mydate >= 1 && mydate <= 6)){document.write("xxx");
}
if (mymonth==12 && (mydate >= 7 && mydate <= 13)){document.write("yyy");
}
if (mymonth==12 && (mydate >= 14 && mydate <= 20)){document.write("zzz");
}
if (mymonth==12 && (mydate >= 21 && mydate <= 30)){document.write("qqq");
}
//-->
</script>

But I need this to change for Advent each year and Advent changes based on when Christmas falls each year:

Advent starts on the Sunday four weeks before Christmas Day. There are four Sundays in Advent, then Christmas Day. The date changes from year to year, depending on which day of the week Christmas fall. Thus, in 2010, Advent began on 28 November. In 2011, it will occur on 27 November.

How do I calculate when the weeks of Advent begin each year?

Trishah
  • 69
  • 8
  • 2
    Get Christmas day in the form of a `Date`. Then work backwards from that day, subtracting 1 day from it, and check the day of the week. As soon as you reach 4 Sundays, that's it. – Ian Apr 22 '13 at 18:48
  • [_Calendrical Calculations_](http://www.amazon.com/Calendrical-Calculations-Millennium-Edward-Reingold/dp/0521777526) deals with a lot of these kinds of things, but I don't have my copy handy so I don't know if it includes an algorithm specifically for the Roman Advent. – Mike Samuel Apr 22 '13 at 18:55

6 Answers6

4

Start with a Date that's exactly 3 weeks before Christmas Eve. Then, walk backwards until the day-of-week is Sunday:

function getAdvent(year) {
  //in javascript months are zero-indexed. january is 0, december is 11
  var d = new Date(new Date(year, 11, 24, 0, 0, 0, 0).getTime() - 3 * 7 * 24 * 60 * 60 * 1000);
  while (d.getDay() != 0) {
    d = new Date(d.getTime() - 24 * 60 * 60 * 1000);
  }

  return d;
}

getAdvent(2013);
// Sun Dec 01 2013 00:00:00 GMT-0600 (CST)

getAdvent(2012);
// Sun Dec 02 2012 00:00:00 GMT-0600 (CST)

getAdvent(2011);
// Sun Nov 27 2011 00:00:00 GMT-0600 (CST)

(2013 and 2012 were tested and verified against the calendar on http://usccb.org/. 2011 was verified against http://christianity.about.com/od/christmas/qt/adventdates2011.htm)

Kapsonfire
  • 1,013
  • 5
  • 17
svidgen
  • 13,744
  • 4
  • 33
  • 58
  • sorry im digging this out, but the december is month 11, not 12 – Kapsonfire Nov 28 '18 at 12:36
  • @Kapsonfire Alas! You are correct. Looks like someone edited this question awhile ago without testing the code, and now for *years*, it would seem, the internet has not known how to correctly calculate the start of Advent ... (Sorry, Internet.) – svidgen Nov 28 '18 at 15:40
  • I dont even know why my first edit suggestion got declined – Kapsonfire Nov 28 '18 at 16:31
2

Here's what I was talking about in my comment:

function getAdvent(year) {
    var date = new Date(year, 11, 25);
    var sundays = 0;
    while (sundays < 4) {
        date.setDate(date.getDate() - 1);
        if (date.getDay() === 0) {
            sundays++;
        }
    }
    return date;
}

DEMO: http://jsfiddle.net/eyUjX/1/

It starts on Christmas day, in the specific year. It goes into the past, day by day, checking for Sunday (where .getDate() returns 0). After 4 of them are encountered, the looping stops and that Date is returned.

So to get 2009's beginning of Advent, use: getAdvent(2009);. It returns a Date object, so you can still work with its methods.

As a reference of its methods: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

Ian
  • 50,146
  • 13
  • 101
  • 111
1

You can get Advent Sunday by adding 3 days to the last Thursday in November, which seems simpler:

function getAdventDay(y){
  var advent=new Date();
  advent.setHours(0,0,0,0);
  //set the year:
  if(typeof y!='number')y=advent.getFullYear();

  //get the last day of november:
  advent.setFullYear(y,10,30);

  //back up to the last thursday in November:
  while(advent.getDay()!==4)advent.setDate(advent.getDate()-1);

  //add 3 days to get Sunday:
  advent.setDate(advent.getDate()+3);

  return advent;
}

getAdventDay(2013)
/*
Sun Dec 01 2013 00:00:00 GMT-0500 (Eastern Standard Time)
*/
kennebec
  • 102,654
  • 32
  • 106
  • 127
1
const getFirstAdvent=function(y){
 const firstAdvent=new Date(y,11,3);
 firstAdvent.setDate(firstAdvent.getDate()-firstAdvent.getDay());
 return firstAdvent;
};

alert(getFirstAdvent(2020)); 
rfb
  • 11
  • 1
  • 8
    Hi rfb, welcome. Please consider adding an explanation. – Tiago Martins Peres Jan 22 '20 at 10:12
  • 1
    This is very clever, but it really needs an explanation. The explanation should cover that in the second line months are zero based so you are starting with December 3rd, and in the third line you are altering the date by going back based on the day of week to land on the Sunday. Bonus points if you change it into a code snippet and change the alert to a console log, or console log in a loop showing several years. – Jason Aller Jan 22 '20 at 17:05
0

I love these challenges, here's how it can be done with recursion. First I find the fourth Sunday. Then I Just keep minusing 7 days until I have the other 3. The variables firstSunday, secondSunday, thirdSunday and fourthSunday - contains the dates.

EDIT: I believe I misunderstood, but the firstSunday variable Will be the date you are looking for.

Demo

Javascript

var year = 2011;//new Date().getFullYear();
var sevenDays = (24*60*60*1000) * 7;

var foundDate;
var findClosestSunday = function(date){
    foundDate = date;
    if (foundDate.getDay() != 0)
        findClosestSunday(new Date(year,11,date.getDate()-1));
    return foundDate;
}

var fourthSunday = findClosestSunday(new Date(year, 11, 23));
var thirdSunday = new Date(fourthSunday.getTime() - sevenDays);
var secondSunday =  new Date(fourthSunday.getTime() - sevenDays *2);
var firstSunday =  new Date(fourthSunday.getTime() - sevenDays *3);

console.log
(
    firstSunday,
    secondSunday,
    thirdSunday,
    fourthSunday
);
Peter Rasmussen
  • 16,474
  • 7
  • 46
  • 63
-1

Javascript works with time in terms of milliseconds since epoch. There are 1000 * 60 * 60 *24 * 7 = 604800000 milliseconds in a week.

You can create a new date in Javascript that is offset from a know date doing this:

var weekTicks, christmas, week0, week1, week2, week3;
weekTicks = 604800000;
christmas = new Date(2013, 12, 25);
week0 = new Date(christmas - weekTicks);
week1 = new Date(week0 - weekTicks);
week2 = new Date(week1 - weekTicks);
week3 = new Date(week2 - weekTicks);

See how that works for you.

Also, the Date.getDay function will work to help you find which day of the month is the first Sunday.

Vivian River
  • 31,198
  • 62
  • 198
  • 313
  • I'd just like to comment on your constants: http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time – Alxandr Apr 22 '13 at 18:57