1 /*
  2  * PersianCal.js - Represent a Persian astronomical (Hijjri) calendar object.
  3  *
  4  * Copyright © 2014-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 
 21 var Calendar = require("./Calendar.js");
 22 
 23 var PersRataDie = require("./PersRataDie.js");
 24 
 25 /**
 26  * @class
 27  * Construct a new Persian astronomical (Hijjri) calendar object. This class encodes
 28  * information about a Persian calendar. This class differs from the
 29  * Persian calendar in that the leap years are calculated based on the
 30  * astronomical observations of the sun in Teheran, instead of calculating
 31  * the leap years based on a regular cyclical rhythm algorithm.<p>
 32  *
 33  * @param {Object=} options Options governing the construction of this instance
 34  * @constructor
 35  * @extends Calendar
 36  */
 37 var PersianCal = function(options) {
 38     this.type = "persian";
 39 
 40     if (options && typeof(options.onLoad) === "function") {
 41         options.onLoad(this);
 42     }
 43 };
 44 
 45 /**
 46  * @private
 47  * @const
 48  * @type Array.<number>
 49  * the lengths of each month
 50  */
 51 PersianCal.monthLengths = [
 52     31,  // Farvardin
 53     31,  // Ordibehesht
 54     31,  // Khordad
 55     31,  // Tir
 56     31,  // Mordad
 57     31,  // Shahrivar
 58     30,  // Mehr
 59     30,  // Aban
 60     30,  // Azar
 61     30,  // Dey
 62     30,  // Bahman
 63     29   // Esfand
 64 ];
 65 
 66 /**
 67  * Return the number of months in the given year. The number of months in a year varies
 68  * for some luni-solar calendars because in some years, an extra month is needed to extend the
 69  * days in a year to an entire solar year. The month is represented as a 1-based number
 70  * where 1=first month, 2=second month, etc.
 71  *
 72  * @param {number} year a year for which the number of months is sought
 73  * @return {number} The number of months in the given year
 74  */
 75 PersianCal.prototype.getNumMonths = function(year) {
 76     return 12;
 77 };
 78 
 79 /**
 80  * Return the number of days in a particular month in a particular year. This function
 81  * can return a different number for a month depending on the year because of things
 82  * like leap years.
 83  *
 84  * @param {number} month the month for which the length is sought
 85  * @param {number} year the year within which that month can be found
 86  * @return {number} the number of days within the given month in the given year
 87  */
 88 PersianCal.prototype.getMonLength = function(month, year) {
 89     if (month !== 12 || !this.isLeapYear(year)) {
 90         return PersianCal.monthLengths[month-1];
 91     } else {
 92         // Month 12, Esfand, has 30 days instead of 29 in leap years
 93         return 30;
 94     }
 95 };
 96 
 97 /**
 98  * Return true if the given year is a leap year in the Persian astronomical calendar.
 99  * @param {number} year the year for which the leap year information is being sought
100  * @return {boolean} true if the given year is a leap year
101  */
102 PersianCal.prototype.isLeapYear = function(year) {
103     var rdNextYear = new PersRataDie({
104         cal: this,
105         year: year + 1,
106         month: 1,
107         day: 1,
108         hour: 0,
109         minute: 0,
110         second: 0,
111         millisecond: 0
112     });
113     var rdThisYear = new PersRataDie({
114         cal: this,
115         year: year,
116         month: 1,
117         day: 1,
118         hour: 0,
119         minute: 0,
120         second: 0,
121         millisecond: 0
122     });
123     return (rdNextYear.getRataDie() - rdThisYear.getRataDie()) > 365;
124 };
125 
126 /**
127  * Return the type of this calendar.
128  *
129  * @return {string} the name of the type of this calendar
130  */
131 PersianCal.prototype.getType = function() {
132     return this.type;
133 };
134 
135 /* register this calendar for the factory method */
136 Calendar._constructors["persian"] = PersianCal;
137 
138 module.exports = PersianCal;
139