Source

ThaiSolarDate.js

/*
 * ThaiSolarDate.js - Represent a date in the ThaiSolar calendar
 *
 * Copyright © 2013-2015, 2018, 2023 JEDLSoft
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var ilib = require("../index.js");
var JSUtils = require("./JSUtils.js");

var IDate = require("./IDate.js");

var ThaiSolarCal = require("./ThaiSolarCal.js");
var GregorianDate = require("./GregorianDate.js");

/**
 * @class
 * Construct a new Thai solar date object. The constructor parameters can
 * contain any of the following properties:
 *
 * <ul>
 * <li><i>unixtime<i> - sets the time of this instance according to the given
 * unix time. Unix time is the number of milliseconds since midnight on Jan 1, 1970.
 *
 * <li><i>julianday</i> - sets the time of this instance according to the given
 * Julian Day instance or the Julian Day given as a float
 *
 * <li><i>year</i> - any integer, including 0
 *
 * <li><i>month</i> - 1 to 12, where 1 means January, 2 means February, etc.
 *
 * <li><i>day</i> - 1 to 31
 *
 * <li><i>hour</i> - 0 to 23. A formatter is used to display 12 hour clocks, but this representation
 * is always done with an unambiguous 24 hour representation
 *
 * <li><i>minute</i> - 0 to 59
 *
 * <li><i>second</i> - 0 to 59
 *
 * <li><i>millisecond</i> - 0 to 999
 *
 * <li><i>timezone</i> - the TimeZone instance or time zone name as a string
 * of this Thai solar date. The date/time is kept in the local time. The time zone
 * is used later if this date is formatted according to a different time zone and
 * the difference has to be calculated, or when the date format has a time zone
 * component in it.
 *
 * <li><i>locale</i> - locale for this Thai solar date. If the time zone is not
 * given, it can be inferred from this locale. For locales that span multiple
 * time zones, the one with the largest population is chosen as the one that
 * represents the locale.
 * </ul>
 *
 * If the constructor is called with another Thai solar date instance instead of
 * a parameter block, the other instance acts as a parameter block and its
 * settings are copied into the current instance.<p>
 *
 * If the constructor is called with no arguments at all or if none of the
 * properties listed above
 * from <i>unixtime</i> through <i>millisecond</i> are present, then the date
 * components are
 * filled in with the current date at the time of instantiation. Note that if
 * you do not give the time zone when defaulting to the current time and the
 * time zone for all of ilib was not set with <i>ilib.setTimeZone()</i>, then the
 * time zone will default to UTC ("Universal Time, Coordinated" or "Greenwich
 * Mean Time").<p>
 *
 * If any of the properties from <i>year</i> through <i>millisecond</i> are not
 * specified in the params, it is assumed that they have the smallest possible
 * value in the range for the property (zero or one).<p>
 *
 *
 * @constructor
 * @extends GregorianDate
 * @param {Object=} params parameters that govern the settings and behaviour of this Thai solar date
 */
var ThaiSolarDate = function(params) {
    var p = {};

    if (params) {
        JSUtils.shallowCopy(params, p);

        // there is 198327 days difference between the Thai solar and
        // Gregorian epochs which is equivalent to 543 years
        if (typeof(p.year) !== 'undefined') {
            p.year -= 543;
        }
        if (typeof(p.rd) !== 'undefined') {
            p.rd -= 198327;
        }
    }
    this.rd = null; // clear these out so that the GregorianDate constructor can set it
    this.offset = undefined;
    //console.log("ThaiSolarDate.constructor: date is " + JSON.stringify(this) + " parent is " + JSON.stringify(this.parent) + " and parent.parent is " + JSON.stringify(this.parent.parent));

    p.onLoad = ilib.bind(this, function(gd) {
        this.cal = new ThaiSolarCal();

        // make sure the year is set correctly from the original params
        if (params && typeof(params.year) !== 'undefined') {
            this.year = parseInt(params.year, 10);
        }

        if (params && typeof(params.onLoad) === "function") {
            params.onLoad(gd);
        }
    });

    GregorianDate.call(this, p);
};

ThaiSolarDate.prototype = new GregorianDate({noinstance: true});
ThaiSolarDate.prototype.parent = GregorianDate.prototype;
ThaiSolarDate.prototype.constructor = ThaiSolarDate;

/**
 * the difference between a zero Julian day and the zero Thai Solar date.
 * This is some 543 years before the start of the Gregorian epoch.
 * @private
 * @type number
 */
ThaiSolarDate.epoch = 1523097.5;

/**
 * Calculate the date components for the current time zone
 * @private
 */
ThaiSolarDate.prototype._calcDateComponents = function () {
    // there is 198327 days difference between the Thai solar and
    // Gregorian epochs which is equivalent to 543 years
    // console.log("ThaiSolarDate._calcDateComponents: date is " + JSON.stringify(this) + " parent is " + JSON.stringify(this.parent) + " and parent.parent is " + JSON.stringify(this.parent.parent));
    this.parent._calcDateComponents.call(this);
    this.year += 543;
};

/**
 * Return the Rata Die (fixed day) number of this date.
 *
 * @protected
 * @return {number} the rd date as a number
 */
ThaiSolarDate.prototype.getRataDie = function() {
    // there is 198327 days difference between the Thai solar and
    // Gregorian epochs which is equivalent to 543 years
    return this.rd.getRataDie() + 198327;
};

/**
 * Return a new Gregorian date instance that represents the first instance of the
 * given day of the week before the current date. The day of the week is encoded
 * as a number where 0 = Sunday, 1 = Monday, etc.
 *
 * @param {number} dow the day of the week before the current date that is being sought
 * @return {IDate} the date being sought
 */
ThaiSolarDate.prototype.before = function (dow) {
    return new ThaiSolarDate({
        rd: this.rd.before(dow, this.offset) + 198327,
        timezone: this.timezone
    });
};

/**
 * Return a new Gregorian date instance that represents the first instance of the
 * given day of the week after the current date. The day of the week is encoded
 * as a number where 0 = Sunday, 1 = Monday, etc.
 *
 * @param {number} dow the day of the week after the current date that is being sought
 * @return {IDate} the date being sought
 */
ThaiSolarDate.prototype.after = function (dow) {
    return new ThaiSolarDate({
        rd: this.rd.after(dow, this.offset) + 198327,
        timezone: this.timezone
    });
};

/**
 * Return a new Gregorian date instance that represents the first instance of the
 * given day of the week on or before the current date. The day of the week is encoded
 * as a number where 0 = Sunday, 1 = Monday, etc.
 *
 * @param {number} dow the day of the week on or before the current date that is being sought
 * @return {IDate} the date being sought
 */
ThaiSolarDate.prototype.onOrBefore = function (dow) {
    return new ThaiSolarDate({
        rd: this.rd.onOrBefore(dow, this.offset) + 198327,
        timezone: this.timezone
    });
};

/**
 * Return a new Gregorian date instance that represents the first instance of the
 * given day of the week on or after the current date. The day of the week is encoded
 * as a number where 0 = Sunday, 1 = Monday, etc.
 *
 * @param {number} dow the day of the week on or after the current date that is being sought
 * @return {IDate} the date being sought
 */
ThaiSolarDate.prototype.onOrAfter = function (dow) {
    return new ThaiSolarDate({
        rd: this.rd.onOrAfter(dow, this.offset) + 198327,
        timezone: this.timezone
    });
};

/**
 * Return the name of the calendar that governs this date.
 *
 * @return {string} a string giving the name of the calendar
 */
ThaiSolarDate.prototype.getCalendar = function() {
    return "thaisolar";
};

//register with the factory method
IDate._constructors["thaisolar"] = ThaiSolarDate;

module.exports = ThaiSolarDate;