1 /** 2 * @fileOverview This file has functions related to getting the day of the week from a date string. 3 * @author <a href="http://www.trevmex.com/">Trevor Menagh</a> 4 * @version 1.0.0 5 * Written on 7/5/2010 (Monday :D) 6 */ 7 8 "use strict"; 9 10 /** 11 * @description An algorithm to calculate the day of the week for any Julian or Gregorian calendar date. 12 * @see <a href="http://en.wikipedia.org/wiki/Zeller%27s_congruence">Zeller's congruence</a> 13 * @function 14 * @param {Number} dayOfMonth The day of the month. 15 * @param {Number} month The month. 16 * @param {Number} year The year. 17 * @param {Boolean} [iso] If true return the ISO week date Day-of-Week (1 = Monday to 7 = Sunday), default is false. 18 * @param {String} [calendarType] "julian" or "gregorian", default is "gregorian". 19 * @param {String[]} [i18nDayMapping] An array of strings mapping "Saturday" to "Friday" in a given language (default is English, ignored if iso is true). 20 * @returns {String|Number} The day of the week ("Monday" to "Sunday"), or the ISO week date Day-of-Week if iso is true. 21 * @throws {MissingParameters} If year, month, or dayOfMonth are not passed in. 22 * @throws {InvalidParameters} If the day of the month or the month are not valid. 23 * @throws {InvalidParameters} If the calendar type is supplied and is not valid. 24 * @throws {InvalidParameters} If iso is supplied and is not valid. 25 * @throws {InvalidParameters} If i18nDayMapping is supplied and is not valid. 26 */ 27 function zeller(dayOfMonth, month, year, iso, calendarType, i18nDayMapping) { 28 // Set the parameters for Zeller's congruence 29 var q = dayOfMonth, 30 m = month, 31 Y = (m < 3) ? year - 1 : year, 32 h, 33 d, 34 i; 35 36 // Validations 37 if (dayOfMonth === undefined || dayOfMonth === null) { 38 throw "MissingParameters: The day of the month is required.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 39 } 40 if (month === undefined || month === null) { 41 throw "MissingParameters: The month is required.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 42 } 43 if (year === undefined || year === null) { 44 throw "MissingParameters: The year is required.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 45 } 46 if (month < 1 || month > 12) { 47 throw "InvalidParameters: The month must be between 1 (January) and 12 (December). " + month + " is invalid.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 48 } 49 if (dayOfMonth < 1 || dayOfMonth > 31) { 50 throw "InvalidParameters: The day of the month must be between 1 and 31. " + dayOfMonth + " is invalid.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 51 } 52 if (month === 4 || month === 6 || month === 9 || month === 11) { 53 if (dayOfMonth > 30) { 54 throw "InvalidParameters: Month " + month + " does not have day " + dayOfMonth + ".\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 55 } 56 } 57 if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) { 58 // This is a leap year 59 if (month === 2 && dayOfMonth > 29) { 60 throw "InvalidParameters: Month 2 (February) does not have day " + dayOfMonth + " this year (" + year + ").\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 61 } 62 } else { 63 // This is not a leap year 64 if (month === 2 && dayOfMonth > 28) { 65 throw "InvalidParameters: Month 2 (February) does not have day " + dayOfMonth + " this year (" + year + ").\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 66 } 67 } 68 if ((calendarType !== undefined && calendarType !== null) && !(calendarType.toLowerCase() === "gregorian" || calendarType.toLowerCase() === "julian")) { 69 throw "InvalidParameters: Calendar type must be \"Gregorian\" or \"Julian\". " + calendarType + " is invalid.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 70 } 71 if ((iso !== undefined && iso !== null) && !(iso === true || iso === false)) { 72 throw "InvalidParameters: ISO must be true or false. " + iso + " is invalid.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 73 } 74 if ((i18nDayMapping !== undefined && i18nDayMapping !== null)) { 75 if (i18nDayMapping.length !== 7) { 76 throw "InvalidParameters: Internationalized Day Mapping must be an array of 7 strings from Saturday to Friday. " + i18nDayMapping + " is invalid.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 77 } 78 for (i = i18nDayMapping.length - 1; i >= 0; i -= 1) { 79 // Check to see if this is a native string 80 if (typeof(i18nDayMapping[i]) !== "string") { 81 // Check to see if this is a String object 82 if (!(i18nDayMapping[i] instanceof String)) { 83 throw "InvalidParameters: Internationalized Day Mapping must be an array of 7 strings from Saturday to Friday. " + i18nDayMapping[i] + " at position " + i + " is invalid.\nFormat: zeller(dayOfMonth, month, year, [iso], [calendarType], [i18nDayMapping])"; 84 } 85 } 86 } 87 } 88 89 // Set default values 90 if (calendarType === undefined || calendarType === null) { 91 calendarType = "gregorian"; 92 } 93 if (iso === undefined || iso === null) { 94 iso = false; 95 } 96 if (iso === false) { 97 if (i18nDayMapping === undefined || i18nDayMapping === null) { 98 i18nDayMapping = ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]; 99 } 100 } 101 102 if (calendarType.toLowerCase() === "gregorian") { 103 h = (Math.floor(q + (Math.floor((m + 1) * 26) / 10) + Y + Math.floor(Y / 4) + (6 * Math.floor(Y / 100)) + Math.floor(Y / 400))) % 7; 104 } else /* calendarType.toLowerCase() === "julian" */ { 105 h = (Math.floor(q + (Math.floor((m + 1) * 26) / 10) + Y + Math.floor(Y / 4) + 5)) % 7; 106 } 107 108 if (iso) { 109 d = ((h + 5) % 7) + 1; 110 } else /* !iso */ { 111 d = i18nDayMapping[h]; 112 } 113 114 return d; 115 } 116 117 /** 118 * @description Given a date and a date format, return which day of the week it is. 119 * @param {String} date A string containing today's date. 120 * @param {Boolean} [iso] If true return the ISO week date Day-of-Week (1 = Monday to 7 = Sunday), default is false. 121 * @param {String} [calendarType] "Julian" or "Gregorian", default is "Gregorian". 122 * @param {String[]} [i18nDayMapping] An array of strings mapping "Saturday" to "Friday" in a given language (default is English) 123 * @returns {String|Number} The day of the week ("Monday" to "Sunday"), or the ISO week date Day-of-Week if iso is true. 124 */ 125 String.prototype.getDay = function (iso, calendarType, i18nDayMapping) { 126 var date = new Date(this); 127 128 return zeller(date.getDate(), date.getMonth() + 1, date.getFullYear(), iso, calendarType, i18nDayMapping); 129 };