'use strict'; var moment = require('moment-timezone'); var utils = require('./utils.cjs'); const PROPS = ['year', 'month', 'day', 'hour', 'minute', 'second']; class CalDate { /** * constructs a new CalDate instance * @param {Object|Date} [opts] - See `set(opts)` * @example * const CalDate = require('caldate') * const caldate = new CalDate('2000-01-01 12:00:00') * caldate.year * //> 2000 * caldate.month * //> 1 */ constructor (opts) { this.set(opts); } static toYear (year) { return utils.toYear(year) } /** * set calendar date * @param {Object|Date} [opts] - defaults to `1900-01-01` * @param {String} opts.year * @param {String} opts.month - January equals to 1, December to 12 * @param {String} opts.day * @param {String} opts.hour * @param {String} opts.minute * @param {String} opts.second * @param {String} opts.duration - defaults to 24 hours */ set (opts) { opts = opts || { year: 1900, month: 1, day: 1 }; if (utils.isDate(opts)) { this.year = opts.getFullYear(); this.month = opts.getMonth() + 1; this.day = opts.getDate(); this.hour = opts.getHours(); this.minute = opts.getMinutes(); this.second = opts.getSeconds(); } else { PROPS.forEach((p) => { this[p] = utils.toNumber(opts[p]) || 0; }); this.month = this.month || 1; this.day = this.day || 1; } this.duration = opts.duration || 24; // duration is in hours return this } /** * checks if Date is equal to `calDate` * @param {CalDate} calDate * @return {Boolean} true if date matches */ isEqualDate (calDate) { let res = true; this.update() ;['year', 'month', 'day'].forEach((p) => { res &= (this[p] === calDate[p]); }); return !!res } /** * get day of week * @return {Number} day of week 0=sunday, 1=monday, ... */ getDay () { return this.toDate().getDay() } /** * set offset per unit * @param {Number} number * @param {String} [unit='d'] - Unit in days `d`, hours `h, minutes `m` * @return {Object} this */ setOffset (number, unit) { if (number) { if (typeof number === 'object') { unit = number.unit; number = number.number; } unit = unit || 'd'; number = parseFloat(number, 10); if (isNaN(number)) { throw new Error('Number required') } const o = { day: 0 }; if (unit === 'd') { o.day = number | 0; number -= o.day; number *= 24; } if (unit === 'd' || unit === 'h') { o.hour = (number % 24) | 0; number -= o.hour; number *= 60; } o.minute = (number % 60) | 0; number -= o.minute; number *= 60; o.second = (number % 60) | 0; this.day += o.day; this.hour += o.hour; this.minute += o.minute; this.second += o.second; } this.update(); return this } /** * set time per hour, minute or second while maintaining duration at midnight * @param {Number} [hour] * @param {Number} [minute] * @param {Number} [second] * @return {Object} this */ setTime (hour, minute, second) { hour = hour || 0; minute = minute || 0; second = second || 0; // the holiday usually ends at midnight - if this is not the case set different duration explicitely this.duration = 24 - (hour + minute / 60 + second / 3600); this.hour = hour; this.minute = minute; this.second = second; this.update(); return this } /** * set duration in hours * @param {Number} duration in hours * @return {Object} this */ setDuration (duration) { this.duration = duration; return this } /** * update internal data to real date * @return {Object} this */ update () { if (this.year) { const d = new CalDate(this.toDate()); PROPS.forEach((p) => { this[p] = d[p]; }); } return this } /** * get end date of calendar date * @return {CalDate} */ toEndDate () { const d = new CalDate(this.toDate()); d.minute += ((this.duration * 60) | 0); d.update(); return d } /** * move internal date to a date in `timezone` * @param {String} timezone - e.g. 'America/New_York' * @return {Date} */ toTimezone (timezone) { if (timezone) { return new Date(moment.tz(this.toString(), timezone).format()) } else { return this.toDate() } } /** * set date from a given `timezone` * @param {Date} dateUTC - date in UTC * @param {String} [timezone] - timezone of dateUTC, e.g. 'America/New_York' * @return {CalDate} self */ fromTimezone (dateUTC, timezone) { if (timezone) { const m = moment.tz(dateUTC, timezone); this.year = m.year(); this.month = m.month() + 1; this.day = m.date(); this.hour = m.hours(); this.minute = m.minutes(); this.second = m.seconds(); } else { this.set(dateUTC); } return this } /** * convert to Date * @return {Date} */ toDate () { return new Date( this.year, this.month - 1, this.day, this.hour, this.minute, this.second, 0 ) } /** * get Date in ISO format */ toISOString () { return this.toString(true) } /** * get Date as String `YYYY-MM-DD HH:MM:SS` */ toString (iso) { const d = new CalDate(this.toDate()); return ( utils.pad0(d.year, 4) + '-' + utils.pad0(d.month) + '-' + utils.pad0(d.day) + (iso ? 'T' : ' ') + utils.pad0(d.hour) + ':' + utils.pad0(d.minute) + ':' + utils.pad0(d.second) + (iso ? 'Z' : '') ) } } exports.CalDate = CalDate;