1 /* 2 * ThaiSolarDate.js - Represent a date in the ThaiSolar calendar 3 * 4 * Copyright © 2013-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 ilib = require("./ilib.js"); 21 var JSUtils = require("./JSUtils.js"); 22 23 var IDate = require("./IDate.js"); 24 25 var ThaiSolarCal = require("./ThaiSolarCal.js"); 26 var GregorianDate = require("./GregorianDate.js"); 27 28 /** 29 * @class 30 * Construct a new Thai solar date object. The constructor parameters can 31 * contain any of the following properties: 32 * 33 * <ul> 34 * <li><i>unixtime<i> - sets the time of this instance according to the given 35 * unix time. Unix time is the number of milliseconds since midnight on Jan 1, 1970. 36 * 37 * <li><i>julianday</i> - sets the time of this instance according to the given 38 * Julian Day instance or the Julian Day given as a float 39 * 40 * <li><i>year</i> - any integer, including 0 41 * 42 * <li><i>month</i> - 1 to 12, where 1 means January, 2 means February, etc. 43 * 44 * <li><i>day</i> - 1 to 31 45 * 46 * <li><i>hour</i> - 0 to 23. A formatter is used to display 12 hour clocks, but this representation 47 * is always done with an unambiguous 24 hour representation 48 * 49 * <li><i>minute</i> - 0 to 59 50 * 51 * <li><i>second</i> - 0 to 59 52 * 53 * <li><i>millisecond</i> - 0 to 999 54 * 55 * <li><i>timezone</i> - the TimeZone instance or time zone name as a string 56 * of this Thai solar date. The date/time is kept in the local time. The time zone 57 * is used later if this date is formatted according to a different time zone and 58 * the difference has to be calculated, or when the date format has a time zone 59 * component in it. 60 * 61 * <li><i>locale</i> - locale for this Thai solar date. If the time zone is not 62 * given, it can be inferred from this locale. For locales that span multiple 63 * time zones, the one with the largest population is chosen as the one that 64 * represents the locale. 65 * </ul> 66 * 67 * If the constructor is called with another Thai solar date instance instead of 68 * a parameter block, the other instance acts as a parameter block and its 69 * settings are copied into the current instance.<p> 70 * 71 * If the constructor is called with no arguments at all or if none of the 72 * properties listed above 73 * from <i>unixtime</i> through <i>millisecond</i> are present, then the date 74 * components are 75 * filled in with the current date at the time of instantiation. Note that if 76 * you do not give the time zone when defaulting to the current time and the 77 * time zone for all of ilib was not set with <i>ilib.setTimeZone()</i>, then the 78 * time zone will default to UTC ("Universal Time, Coordinated" or "Greenwich 79 * Mean Time").<p> 80 * 81 * If any of the properties from <i>year</i> through <i>millisecond</i> are not 82 * specified in the params, it is assumed that they have the smallest possible 83 * value in the range for the property (zero or one).<p> 84 * 85 * 86 * @constructor 87 * @extends GregorianDate 88 * @param {Object=} params parameters that govern the settings and behaviour of this Thai solar date 89 */ 90 var ThaiSolarDate = function(params) { 91 var p = {}; 92 93 if (params) { 94 JSUtils.shallowCopy(params, p); 95 96 // there is 198327 days difference between the Thai solar and 97 // Gregorian epochs which is equivalent to 543 years 98 if (typeof(p.year) !== 'undefined') { 99 p.year -= 543; 100 } 101 if (typeof(p.rd) !== 'undefined') { 102 p.rd -= 198327; 103 } 104 } 105 this.rd = null; // clear these out so that the GregorianDate constructor can set it 106 this.offset = undefined; 107 //console.log("ThaiSolarDate.constructor: date is " + JSON.stringify(this) + " parent is " + JSON.stringify(this.parent) + " and parent.parent is " + JSON.stringify(this.parent.parent)); 108 109 p.onLoad = ilib.bind(this, function(gd) { 110 this.cal = new ThaiSolarCal(); 111 112 // make sure the year is set correctly from the original params 113 if (params && typeof(params.year) !== 'undefined') { 114 this.year = parseInt(params.year, 10); 115 } 116 117 if (params && typeof(params.onLoad) === "function") { 118 params.onLoad(gd); 119 } 120 }); 121 122 GregorianDate.call(this, p); 123 }; 124 125 ThaiSolarDate.prototype = new GregorianDate({noinstance: true}); 126 ThaiSolarDate.prototype.parent = GregorianDate.prototype; 127 ThaiSolarDate.prototype.constructor = ThaiSolarDate; 128 129 /** 130 * the difference between a zero Julian day and the zero Thai Solar date. 131 * This is some 543 years before the start of the Gregorian epoch. 132 * @private 133 * @type number 134 */ 135 ThaiSolarDate.epoch = 1523097.5; 136 137 /** 138 * Calculate the date components for the current time zone 139 * @protected 140 */ 141 ThaiSolarDate.prototype._calcDateComponents = function () { 142 // there is 198327 days difference between the Thai solar and 143 // Gregorian epochs which is equivalent to 543 years 144 // console.log("ThaiSolarDate._calcDateComponents: date is " + JSON.stringify(this) + " parent is " + JSON.stringify(this.parent) + " and parent.parent is " + JSON.stringify(this.parent.parent)); 145 this.parent._calcDateComponents.call(this); 146 this.year += 543; 147 }; 148 149 /** 150 * Return the Rata Die (fixed day) number of this date. 151 * 152 * @protected 153 * @return {number} the rd date as a number 154 */ 155 ThaiSolarDate.prototype.getRataDie = function() { 156 // there is 198327 days difference between the Thai solar and 157 // Gregorian epochs which is equivalent to 543 years 158 return this.rd.getRataDie() + 198327; 159 }; 160 161 /** 162 * Return a new Gregorian date instance that represents the first instance of the 163 * given day of the week before the current date. The day of the week is encoded 164 * as a number where 0 = Sunday, 1 = Monday, etc. 165 * 166 * @param {number} dow the day of the week before the current date that is being sought 167 * @return {IDate} the date being sought 168 */ 169 ThaiSolarDate.prototype.before = function (dow) { 170 return new ThaiSolarDate({ 171 rd: this.rd.before(dow, this.offset) + 198327, 172 timezone: this.timezone 173 }); 174 }; 175 176 /** 177 * Return a new Gregorian date instance that represents the first instance of the 178 * given day of the week after the current date. The day of the week is encoded 179 * as a number where 0 = Sunday, 1 = Monday, etc. 180 * 181 * @param {number} dow the day of the week after the current date that is being sought 182 * @return {IDate} the date being sought 183 */ 184 ThaiSolarDate.prototype.after = function (dow) { 185 return new ThaiSolarDate({ 186 rd: this.rd.after(dow, this.offset) + 198327, 187 timezone: this.timezone 188 }); 189 }; 190 191 /** 192 * Return a new Gregorian date instance that represents the first instance of the 193 * given day of the week on or before the current date. The day of the week is encoded 194 * as a number where 0 = Sunday, 1 = Monday, etc. 195 * 196 * @param {number} dow the day of the week on or before the current date that is being sought 197 * @return {IDate} the date being sought 198 */ 199 ThaiSolarDate.prototype.onOrBefore = function (dow) { 200 return new ThaiSolarDate({ 201 rd: this.rd.onOrBefore(dow, this.offset) + 198327, 202 timezone: this.timezone 203 }); 204 }; 205 206 /** 207 * Return a new Gregorian date instance that represents the first instance of the 208 * given day of the week on or after the current date. The day of the week is encoded 209 * as a number where 0 = Sunday, 1 = Monday, etc. 210 * 211 * @param {number} dow the day of the week on or after the current date that is being sought 212 * @return {IDate} the date being sought 213 */ 214 ThaiSolarDate.prototype.onOrAfter = function (dow) { 215 return new ThaiSolarDate({ 216 rd: this.rd.onOrAfter(dow, this.offset) + 198327, 217 timezone: this.timezone 218 }); 219 }; 220 221 /** 222 * Return the name of the calendar that governs this date. 223 * 224 * @return {string} a string giving the name of the calendar 225 */ 226 ThaiSolarDate.prototype.getCalendar = function() { 227 return "thaisolar"; 228 }; 229 230 //register with the factory method 231 IDate._constructors["thaisolar"] = ThaiSolarDate; 232 233 module.exports = ThaiSolarDate; 234