1 /*
  2  * PersAlsoRataDie.js - Represent an RD date in the Persian algorithmic calendar
  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 var MathUtils = require("./MathUtils.js");
 21 var PersianAlgoCal = require("./PersianAlgoCal.js");
 22 var RataDie = require("./RataDie.js");
 23 
 24 /**
 25  * @class
 26  * Construct a new Persian RD date number object. The constructor parameters can
 27  * contain any of the following properties:
 28  *
 29  * <ul>
 30  * <li><i>unixtime<i> - sets the time of this instance according to the given
 31  * unix time. Unix time is the number of milliseconds since midnight on Jan 1, 1970, Gregorian
 32  *
 33  * <li><i>julianday</i> - sets the time of this instance according to the given
 34  * Julian Day instance or the Julian Day given as a float
 35  *
 36  * <li><i>year</i> - any integer, including 0
 37  *
 38  * <li><i>month</i> - 1 to 12, where 1 means Farvardin, 2 means Ordibehesht, etc.
 39  *
 40  * <li><i>day</i> - 1 to 31
 41  *
 42  * <li><i>hour</i> - 0 to 23. A formatter is used to display 12 hour clocks, but this representation
 43  * is always done with an unambiguous 24 hour representation
 44  *
 45  * <li><i>minute</i> - 0 to 59
 46  *
 47  * <li><i>second</i> - 0 to 59
 48  *
 49  * <li><i>millisecond</i> - 0 to 999
 50  *
 51  * <li><i>date</i> - use the given intrinsic Javascript date to initialize this one.
 52  * </ul>
 53  *
 54  * If the constructor is called with another Persian date instance instead of
 55  * a parameter block, the other instance acts as a parameter block and its
 56  * settings are copied into the current instance.<p>
 57  *
 58  * If the constructor is called with no arguments at all or if none of the
 59  * properties listed above are present, then the RD is calculate based on
 60  * the current date at the time of instantiation. <p>
 61  *
 62  * If any of the properties from <i>year</i> through <i>millisecond</i> are not
 63  * specified in the params, it is assumed that they have the smallest possible
 64  * value in the range for the property (zero or one).<p>
 65  *
 66  *
 67  * @private
 68  * @constructor
 69  * @extends RataDie
 70  * @param {Object=} params parameters that govern the settings and behaviour of this Persian RD date
 71  */
 72 var PersAlgoRataDie = function(params) {
 73     this.cal = params && params.cal || new PersianAlgoCal();
 74     this.rd = NaN;
 75     RataDie.call(this, params);
 76 };
 77 
 78 PersAlgoRataDie.prototype = new RataDie();
 79 PersAlgoRataDie.prototype.parent = RataDie;
 80 PersAlgoRataDie.prototype.constructor = PersAlgoRataDie;
 81 
 82 /**
 83  * The difference between a zero Julian day and the first Persian date
 84  * @private
 85  * @type number
 86  */
 87 PersAlgoRataDie.prototype.epoch = 1948319.5;
 88 
 89 /**
 90  * @private
 91  * @const
 92  * @type Array.<number>
 93  * the cumulative lengths of each month, for a non-leap year
 94  */
 95 PersAlgoRataDie.cumMonthLengths = [
 96     0,    // Farvardin
 97     31,   // Ordibehesht
 98     62,   // Khordad
 99     93,   // Tir
100     124,  // Mordad
101     155,  // Shahrivar
102     186,  // Mehr
103     216,  // Aban
104     246,  // Azar
105     276,  // Dey
106     306,  // Bahman
107     336,  // Esfand
108     365
109 ];
110 
111 /**
112  * Calculate the Rata Die (fixed day) number of the given date from the
113  * date components.
114  *
115  * @protected
116  * @param {Object} date the date components to calculate the RD from
117  */
118 PersAlgoRataDie.prototype._setDateComponents = function(date) {
119     var year = this.cal.equivalentCycleYear(date.year);
120     var y = date.year - (date.year >= 0 ? 474 : 473);
121     var rdOfYears = 1029983 * Math.floor(y/2820) + 365 * (year - 1) + Math.floor((682 * year - 110) / 2816);
122     var dayInYear = (date.month > 1 ? PersAlgoRataDie.cumMonthLengths[date.month-1] : 0) + date.day;
123     var rdtime = (date.hour * 3600000 +
124         date.minute * 60000 +
125         date.second * 1000 +
126         date.millisecond) /
127         86400000;
128 
129     /*
130     // console.log("getRataDie: converting " +  JSON.stringify(this));
131     console.log("getRataDie: year is " +  year);
132     console.log("getRataDie: rd of years is " +  rdOfYears);
133     console.log("getRataDie: day in year is " +  dayInYear);
134     console.log("getRataDie: rdtime is " +  rdtime);
135     console.log("getRataDie: rd is " +  (rdOfYears + dayInYear + rdtime));
136     */
137 
138     this.rd = rdOfYears + dayInYear + rdtime;
139 };
140 
141 /**
142  * Return the rd number of the particular day of the week on or before the
143  * given rd. eg. The Sunday on or before the given rd.
144  * @private
145  * @param {number} rd the rata die date of the reference date
146  * @param {number} dayOfWeek the day of the week that is being sought relative
147  * to the current date
148  * @return {number} the rd of the day of the week
149  */
150 PersAlgoRataDie.prototype._onOrBefore = function(rd, dayOfWeek) {
151     return rd - MathUtils.mod(Math.floor(rd) - dayOfWeek - 3, 7);
152 };
153 
154 module.exports = PersAlgoRataDie;