/**
 * Level of precision required when comparing two dates
 * Day: yyyy-mm-dd
 * Month: yyyy-mm
 * Year: yyyy
 */
export var DatePrecision;
(function (DatePrecision) {
    DatePrecision["DAY"] = "day";
    DatePrecision["MONTH"] = "month";
    DatePrecision["YEAR"] = "year";
})(DatePrecision || (DatePrecision = {}));
export var DateComparison;
(function (DateComparison) {
    DateComparison[DateComparison["IS_BEFORE"] = -1] = "IS_BEFORE";
    DateComparison[DateComparison["IS_EQUAL"] = 0] = "IS_EQUAL";
    DateComparison[DateComparison["IS_AFTER"] = 1] = "IS_AFTER";
})(DateComparison || (DateComparison = {}));
export var DATE_FORMAT_REGEX = /(^(\d{1,4})[\.|\\\/|-](\d{1,2})(([\.|\\\/|-])(\d{1,4}))?)$/;
var ModulDate = /** @class */ (function () {
    function ModulDate(year, month, day) {
        switch (arguments.length) {
            case 1:
                var value = arguments[0];
                if (value instanceof ModulDate) {
                    this.innerDate = new Date(value.fullYear(), value.month(), value.day());
                }
                else if (value instanceof Date) {
                    this.innerDate = new Date(value);
                }
                else if (typeof (value) === 'string') {
                    this.dateFromString(value);
                }
                else {
                    var date_1 = new Date();
                    this.innerDate = new Date(date_1.getFullYear(), date_1.getMonth(), date_1.getDate());
                }
                break;
            case 3:
                this.innerDate = new Date(year, month, day);
                break;
            default:
                var date = new Date();
                this.innerDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
        }
    }
    /**
     * Check if the current date is before or equal to the received date.
     *
     * @param otherDate date to be compared with
     * @param precision level of precision for comparison @see DatePrecision
     */
    ModulDate.prototype.isSameOrBefore = function (otherDate, precision) {
        if (precision === void 0) { precision = DatePrecision.DAY; }
        return this.toTime(otherDate.innerDate, precision) >= this.toTime(this.innerDate, precision);
    };
    /**
     * Check if the current date is strictly before to the received date.
     *
     * @param otherDate date to be compared with
     * @param precision level of precision for comparison @see DatePrecision
     */
    ModulDate.prototype.isBefore = function (otherDate, precision) {
        if (precision === void 0) { precision = DatePrecision.DAY; }
        return this.toTime(otherDate.innerDate, precision) > this.toTime(this.innerDate, precision);
    };
    /**
     * Check if the current date is equal to the received date.
     *
     * @param otherDate date to be compared with
     * @param precision level of precision for comparison @see DatePrecision
     */
    ModulDate.prototype.isSame = function (otherDate, precision) {
        if (precision === void 0) { precision = DatePrecision.DAY; }
        return this.toTime(otherDate.innerDate, precision) === this.toTime(this.innerDate, precision);
    };
    /**
     * Check if the current date is equal or after to the received date.
     *
     * @param otherDate date to be compared with
     * @param precision level of precision for comparison @see DatePrecision
     */
    ModulDate.prototype.isSameOrAfter = function (otherDate, precision) {
        if (precision === void 0) { precision = DatePrecision.DAY; }
        return this.toTime(otherDate.innerDate, precision) <= this.toTime(this.innerDate, precision);
    };
    /**
     * Check if the current date or after to the received date.
     *
     * @param otherDate date to be compared with
     * @param precision level of precision for comparison @see DatePrecision
     */
    ModulDate.prototype.isAfter = function (otherDate, precision) {
        if (precision === void 0) { precision = DatePrecision.DAY; }
        return this.toTime(otherDate.innerDate, precision) < this.toTime(this.innerDate, precision);
    };
    /**
     * Check if the current date is equal to one of the bounds or between them.
     *
     * @param lowerDate lower bound
     * @param higherDate higher bound
     * @param precision level of precision for comparison @see DatePrecision
     */
    ModulDate.prototype.isBetween = function (lowerDate, higherDate, precision) {
        if (precision === void 0) { precision = DatePrecision.DAY; }
        return this.toTime(lowerDate.innerDate, precision) <= this.toTime(this.innerDate, precision)
            && this.toTime(this.innerDate, precision) <= this.toTime(higherDate.innerDate, precision);
    };
    /**
     * Check if the current date is strictly between bounds them.
     *
     * @param lowerDate lower bound
     * @param higherDate higher bound
     * @param precision level of precision for comparison @see DatePrecision
     */
    ModulDate.prototype.isBetweenStrict = function (lowerDate, higherDate, precision) {
        if (precision === void 0) { precision = DatePrecision.DAY; }
        return this.toTime(lowerDate.innerDate, precision) < this.toTime(this.innerDate, precision)
            && this.toTime(this.innerDate, precision) < this.toTime(higherDate.innerDate, precision);
    };
    /**
     * Compare the current date with the received date to determine if the current date is before, equal or after the
     * received date
     *
     * @param date date to be compared with
     * @returns @see DateComparison
     */
    ModulDate.prototype.compare = function (date) {
        var current = this.toTime(this.innerDate, DatePrecision.DAY);
        var other = this.toTime(date.innerDate, DatePrecision.DAY);
        if (current < other) {
            return DateComparison.IS_BEFORE;
        }
        else if (current > other) {
            return DateComparison.IS_AFTER;
        }
        return DateComparison.IS_EQUAL;
    };
    /**
     * format date string as YYYY-MM-DD
     */
    ModulDate.prototype.toString = function () {
        var month = this.padString((this.innerDate.getMonth() + 1).toString());
        var day = this.padString(this.innerDate.getDate().toString());
        return this.fullYear() + "-" + month + "-" + day;
    };
    /**
     * format date following the date part of the standard ISO-8601
     */
    ModulDate.prototype.toISOString = function () {
        return this.innerDate.toISOString();
    };
    /**
     * format date following the locale representation of a date
     */
    ModulDate.prototype.toLocaleDateString = function () {
        return this.innerDate.toLocaleDateString();
    };
    /**
     * Getter for the year value
     */
    ModulDate.prototype.fullYear = function () {
        return this.innerDate.getFullYear();
    };
    /**
     * Getter for the month value
     */
    ModulDate.prototype.month = function () {
        return this.innerDate.getMonth();
    };
    /**
     * Getter for the day of the month value
     */
    ModulDate.prototype.day = function () {
        return this.innerDate.getDate();
    };
    /**
     * Getter for the day of the week value
     */
    ModulDate.prototype.dayOfWeek = function () {
        return this.innerDate.getDay();
    };
    /**
     * Compares if two dates are equals
     *
     * @param otherDate date to compare with
     */
    ModulDate.prototype.equals = function (otherDate) {
        if (otherDate instanceof Date) {
            return this.toTime(otherDate, DatePrecision.DAY) === this.toTime(this.innerDate, DatePrecision.DAY);
        }
        else if (otherDate instanceof ModulDate) {
            return this.toTime(otherDate.innerDate, DatePrecision.DAY) === this.toTime(this.innerDate, DatePrecision.DAY);
        }
        return false;
    };
    /**
     * Calculates the number of days between the current date and the received date.
     *
     * @param other
     * @return Number of days in absolute format
     */
    ModulDate.prototype.deltaInDays = function (other) {
        return Math.round(Math.abs(other.innerDate.getTime() - this.innerDate.getTime()) / (1000 * 3600 * 24));
    };
    /**
     * Add an unit of time to a copy of the current date and return it.
     *
     * @param valueToAdd The value to add to the time unit.
     * @param unitOfTime The kind of time unit to be added.
     * @return A new Date
     */
    ModulDate.prototype.add = function (valueToAdd, unitOfTime) {
        return this.subtract(-valueToAdd, unitOfTime);
    };
    /**
     * subtract an unit of time to a copy of the current date and return it.
     *
     * @param valueToSubtract The value to add to the time unit.
     * @param unitOfTime The kind of time unit to be added.
     * @return A new Date
     */
    ModulDate.prototype.subtract = function (valueToSubtract, unitOfTime) {
        if (unitOfTime === void 0) { unitOfTime = DatePrecision.YEAR; }
        var newDate = new Date(this.innerDate);
        switch (unitOfTime) {
            case DatePrecision.YEAR:
                newDate.setFullYear(newDate.getFullYear() - valueToSubtract);
                break;
            case DatePrecision.MONTH:
                newDate.setMonth(newDate.getMonth() - valueToSubtract);
                break;
            case DatePrecision.DAY:
                var dateOffset = (24 * 60 * 60 * 1000) * valueToSubtract;
                newDate.setTime(newDate.getTime() - dateOffset);
                break;
            default: throw new Error("modul-date: Unknown substract unitOfTime: " + unitOfTime);
        }
        return newDate;
    };
    /**
     * Return a date representing the end of the day of a given date (23:59:59).
     *
     * @return A new Date
     */
    ModulDate.prototype.beginOfDay = function () {
        return new Date(this.innerDate.getFullYear(), this.innerDate.getMonth(), this.innerDate.getDate(), 0, 0, 0, 0);
    };
    /**
     * Return a date representing the end of the day of a given date (23:59:59).
     *
     * @return A new Date
     */
    ModulDate.prototype.endOfDay = function () {
        return new Date(this.innerDate.getFullYear(), this.innerDate.getMonth(), this.innerDate.getDate(), 23, 59, 59, 999);
    };
    ModulDate.prototype.toDate = function () {
        return this.innerDate;
    };
    ModulDate.prototype.dateFromString = function (value) {
        if (value === '') {
            this.innerDate = new Date();
        }
        else {
            this.innerDate = this.convertStringToDate(value);
        }
    };
    ModulDate.prototype.convertStringToDate = function (value) {
        // If the string is an iso string, we use it directly.
        if (value.split('T')[1]) {
            return new Date(value);
        }
        // Otherwise we try to build the date from a partial date string (2010-12-01 or 2010/12/01)
        if (!DATE_FORMAT_REGEX.test(value)) {
            throw Error("Impossible to find date parts in date");
        }
        else {
            var stringToDelete = /[\.|\\/|-]/g;
            var parts = value.split(stringToDelete);
            var first = parts[0];
            var second = parts[1];
            var third = parts[2] || '1';
            if (parseInt(first, 10) > 12 && parseInt(second, 10) > 12 && parseInt(third, 10) > 12) {
                throw Error("No suitable month value");
            }
            else if (parseInt(first, 10) > 31 && parseInt(third, 10) > 31) {
                throw Error("No suitable day of month value");
            }
            if (third.length === 4 || third.length > first.length) {
                third = [first, first = third][0];
            }
            var year = (first.length === 2) ? '20' + first : first;
            if (parseInt(second, 10) > 12) {
                third = [second, second = third][0];
            }
            var month = this.padString(second);
            var day = this.padString(third);
            var date = new Date(parseInt(year, 10), parseInt(month, 10) - 1, parseInt(day, 10));
            return date;
        }
    };
    ModulDate.prototype.padString = function (input) {
        return ('000' + input).slice(-2);
    };
    ModulDate.prototype.toTime = function (date, precision) {
        var toTimeDate;
        switch (precision) {
            case DatePrecision.YEAR:
                toTimeDate = new Date(date.getFullYear(), 1, 1);
                break;
            case DatePrecision.MONTH:
                toTimeDate = new Date(date.getFullYear(), date.getMonth(), 1);
                break;
            default: // DatePrecision.DAY:
                toTimeDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
        }
        return toTimeDate.getTime();
    };
    return ModulDate;
}());
export default ModulDate;
//# sourceMappingURL=modul-date.js.map