1 /*
  2  * IslamicCal.js - Represent a Islamic calendar object.
  3  *
  4  * Copyright © 2012-2015, 2018, JEDLSoft
  5  *
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  *
 10  *     http://www.apache.org/licenses/LICENSE-2.0
 11  *
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  *
 16  * See the License for the specific language governing permissions and
 17  * limitations under the License.
 18  */
 19 
 20 var MathUtils = require("./MathUtils.js");
 21 var Calendar = require("./Calendar.js");
 22 
 23 /**
 24  * @class
 25  * Construct a new Islamic calendar object. This class encodes information about
 26  * the civil Islamic calendar. The civil Islamic calendar is a tabular islamic
 27  * calendar where the dates are calculated by arithmetic rules. This differs from
 28  * the religious Islamic calendar which is used to mark the beginning of particular
 29  * holidays. The religious calendar depends on the first sighting of the new
 30  * crescent moon to determine the first day of the new month. Because humans and
 31  * weather are both involved, the actual time of sighting varies, so it is not
 32  * really possible to precalculate the religious calendar. Certain groups, such
 33  * as the Islamic Society of North America, decreed in in 2007 that they will use
 34  * a calendar based on calculations rather than observations to determine the
 35  * beginning of lunar months, and therefore the dates of holidays.<p>
 36  *
 37  * @param {Object=} options Options governing the construction of this instance
 38  * @constructor
 39  * @extends Calendar
 40  */
 41 var IslamicCal = function(options) {
 42     this.type = "islamic";
 43 
 44     if (options && typeof(options.onLoad) === "function") {
 45         options.onLoad(this);
 46     }
 47 };
 48 
 49 /**
 50  * the lengths of each month
 51  * @private
 52  * @const
 53  * @type Array.<number>
 54  */
 55 IslamicCal.monthLengths = [
 56     30,  /* Muharram */
 57     29,  /* Saffar */
 58     30,  /* Rabi'I */
 59     29,  /* Rabi'II */
 60     30,  /* Jumada I */
 61     29,  /* Jumada II */
 62     30,  /* Rajab */
 63     29,  /* Sha'ban */
 64     30,  /* Ramadan */
 65     29,  /* Shawwal */
 66     30,  /* Dhu al-Qa'da */
 67     29   /* Dhu al-Hijja */
 68 ];
 69 
 70 
 71 /**
 72  * Return the number of months in the given year. The number of months in a year varies
 73  * for luni-solar calendars because in some years, an extra month is needed to extend the
 74  * days in a year to an entire solar year. The month is represented as a 1-based number
 75  * where 1=first month, 2=second month, etc.
 76  *
 77  * @param {number} year a year for which the number of months is sought
 78  */
 79 IslamicCal.prototype.getNumMonths = function(year) {
 80     return 12;
 81 };
 82 
 83 /**
 84  * Return the number of days in a particular month in a particular year. This function
 85  * can return a different number for a month depending on the year because of things
 86  * like leap years.
 87  *
 88  * @param {number} month the month for which the length is sought
 89  * @param {number} year the year within which that month can be found
 90  * @return {number} the number of days within the given month in the given year
 91  */
 92 IslamicCal.prototype.getMonLength = function(month, year) {
 93     if (month !== 12) {
 94         return IslamicCal.monthLengths[month-1];
 95     } else {
 96         return this.isLeapYear(year) ? 30 : 29;
 97     }
 98 };
 99 
100 /**
101  * Return true if the given year is a leap year in the Islamic calendar.
102  * The year parameter may be given as a number, or as a IslamicDate object.
103  * @param {number} year the year for which the leap year information is being sought
104  * @return {boolean} true if the given year is a leap year
105  */
106 IslamicCal.prototype.isLeapYear = function(year) {
107     return (MathUtils.mod((14 + 11 * year), 30) < 11);
108 };
109 
110 /**
111  * Return the type of this calendar.
112  *
113  * @return {string} the name of the type of this calendar
114  */
115 IslamicCal.prototype.getType = function() {
116     return this.type;
117 };
118 
119 
120 /*register this calendar for the factory method */
121 Calendar._constructors["islamic"] = IslamicCal;
122 
123 module.exports = IslamicCal;
124