Add Doomsday algorithm. #35

Merged
merged 1 commit into from Nov 27, 2011
View
18 examples/date.winxed
@@ -0,0 +1,18 @@
+// Doomsday Algorithm example.
+
+function main[main]()
+{
+ var rosella = load_packfile("rosella/core.pbc");
+ var(Rosella.initialize_rosella)("date");
+
+ var d = new Rosella.Date.Doomsday();
+
+ print("Doomsday for 2011: ");
+ say(d.get_day_of_week(d.__get_dday(2011)));
+
+ print("11/26/2011 was a... ");
+ say(d.get_day_of_week(d.get_day(2011, 11, 26)));
+
+ print("9/11/2001 was a... ");
+ say(d.get_day_of_week(d.get_day(2001, 9, 11)));
+}
View
4 setup.winxed
@@ -329,6 +329,10 @@ function setup_experimental_libraries(var rosella)
"random/randomnumber/BoxMullerNormal",
"random/randomnumber/MersenneTwister"
);
+
+ setup_unstable_lib(rosella, "date", [],
+ "date/Doomsday"
+ );
}
function setup_utilities(var rosella)
View
60 src/unstable/date/Doomsday.winxed
@@ -0,0 +1,60 @@
+/* Doomsday Algorithm
+ This class implements the Doomsday Algorithm, a fast, computationally-simple method
+ to determine the day of week of any day.
+*/
+class Rosella.Date.Doomsday
+{
+ var doomsdays;
+ var days;
+
+ function Doomsday()
+ {
+ self.doomsdays = [ 3, 28, 7, 4, 9, 6, 11, 8, 5, 10, 7, 12 ]; // doomsdays[N] is the day of month N that falls
+ // on a doomsday.
+ self.days = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
+ }
+
+ function get_day(int year, int month, int day)
+ {
+ if (year < 1)
+ Rosella.Error.invalid(__FUNCTION__, "Bad year");
+ if (month < 1 || month > 12)
+ Rosella.Error.invalid(__FUNCTION__, "Bad month");
+ if (day < 1 || day > 31)
+ Rosella.Error.invalid(__FUNCTION__, "Bad day");
+
+ // Determine the doomsday for this year.
+ int dday = self.__get_dday(year);
+
+ int leap = (year % 4) == 0;
+ int anchor = self.doomsdays[month - 1];
+ if (leap && month <= 2)
+ anchor += 1; // the anchor date for jan/feb is +1 for leap years.
+
+ while (day < anchor)
+ day += 7; // skip forward weeks if necessary.
+ while (day >= (anchor + 7))
+ day -= 7; // skip backward weeks if necessary.
+
+ // At this point day is during the week of anchor.
+ __ASSERT__(anchor <= day < anchor + 7);
+
+ int dayoffset = day - anchor;
+ day = (dday + dayoffset) % 7;
+
+ return day;
+ }
+
+ function get_day_of_week(int day)
+ {
+ if (day < 0 || day > 6)
+ Rosella.Error.invalid(__FUNCTION__, "Bad day");
+
+ return self.days[day];
+ }
+
+ function __get_dday(int year)
+ {
+ return (2 + year + (year / 4) - (year / 100) + (year / 400)) % 7;
+ }
+}