magic-date
Version:
A simple date utility for javascript
748 lines (747 loc) • 26.8 kB
JavaScript
"use strict";
/**
* @author Peter Ukonu
* @email [pukonu@gmail.com]
* @create date 2018-07-06 02:51:23
* @modify date 2018-07-06 02:53:23
* @revision date 2020-05-20 03:00:00 - v2
* @desc A date utility class to handle all sort of manipulation on a date
*/
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
exports.__esModule = true;
// TODO: work out the ts-ignore
// test by pasting it into retrace magic date
var TimeFormat;
(function (TimeFormat) {
TimeFormat[TimeFormat["ISO8601"] = 0] = "ISO8601";
})(TimeFormat || (TimeFormat = {}));
/**
* A class to perform some magic function on Javascript date
* e.g.
* 1. For 3 weeks ahead of today its simple MagicDate().next("3 weeks")
* 2. For 2 days backwars MagicDate().next("-2 days")
* 3. For the first date of the current week MagicDate().getWeekFirstDate()
* 4. Last date of the current month MagicDate().getMonthLastDate()
* 5. Date factory MagicDate.makeDate({year: 2018, month: 3, day: 18})
* 6. Cast MagicDate object to a format <dateObject>.setCast("%Y-%m").toString()
* 7. Check if current year is a leap year MagicDate().isLeapYear()
* 8. Return an array of dates between one and another MagicDate.getDateFromTo(start: MagicDate, end: MagicDate)
*
*/
var MagicDate = /** @class */ (function () {
function MagicDate(date, options) {
if (date === void 0) { date = null; }
if (options === void 0) { options = {}; }
this.year = null;
this.month = null;
this.day = null;
this.hour = null;
this.minute = null;
this.second = null;
this.microSecond = null;
this.timezoneStr = "+00:00";
this.weekday = null;
this.weekdayNumeric = null;
this.weeknum = null;
this.weekStart = MagicDate.WEEKDAYS[0];
this.leapYear = false;
this.yearStr = null;
this.monthStr = null;
this.dayStr = null;
this.hourStr = null;
this.minuteStr = null;
this.secondStr = null;
this.microSecondStr = null;
this.timezoneOffset = null;
this.dtTime = 0;
this.dtObj = null;
this._castMask = null;
this.options = __assign({ weekStart: MagicDate.DEFAULT_WEEK_START, microSecondsLength: MagicDate.DEFAULT_MICRO_SECONDS_LENGTH, dateIso: MagicDate.DEFAULT_ISO_FORMAT }, options);
return this.now(date);
}
/**
* A public static method in MagicDate which represent a Factory for making dateObjects
* @param dateFactoryConfig
* @param options
*/
MagicDate.makeDate = function (dateFactoryConfig, options) {
if (options === void 0) { options = {}; }
var dateObject = new MagicDate();
var __microSecondLength = options.microSecondsLength || MagicDate.DEFAULT_MICRO_SECONDS_LENGTH;
try {
if (dateFactoryConfig.dt) {
// @ts-ignore
dateObject.dtObj = new Date(dateFactoryConfig.dt);
}
else {
var __dateObject_1 = MagicDate.SIMPLE_DATE;
var __isoDate_1 = {};
[
"year",
"month",
"day",
"hour",
"min",
"sec",
"microSecond"
].map(function (v) {
var _a, _b, _c, _d;
var validityError = MagicDate.validateDateConfig(parseInt((_a = dateFactoryConfig[v]) === null || _a === void 0 ? void 0 : _a.toString()), v);
if (validityError) {
throw new Error(validityError);
}
__dateObject_1[v] = dateFactoryConfig[v] || __dateObject_1[v];
switch (v) {
case "year":
__isoDate_1[v] = (_b = __dateObject_1[v]) === null || _b === void 0 ? void 0 : _b.toString();
break;
case "microSecond":
__isoDate_1[v] = MagicDate.padding(((_c = __dateObject_1[v]) === null || _c === void 0 ? void 0 : _c.toString()) || "", __microSecondLength, "0");
break;
default:
__isoDate_1[v] = MagicDate.padding(((_d = __dateObject_1[v]) === null || _d === void 0 ? void 0 : _d.toString()) || "", 2, "0");
}
});
var timezoneStr = MagicDate.makeTimezoneStr(__dateObject_1.timezoneOffset);
// @ts-ignore
var isoDateStr = __isoDate_1["year"] + "-" + __isoDate_1["month"] + "-" + __isoDate_1["day"] + " " + __isoDate_1["hour"] + ":" + __isoDate_1["min"] + ":" + __isoDate_1["sec"] + "." + __isoDate_1["microSecond"] + timezoneStr;
return MagicDate.makeDateFromString(isoDateStr, options);
}
}
catch (e) {
console.error("To make a new date, you must pass in the year month and day into the makeDate " +
"function arguments", e);
}
dateObject._toNumber()._analyseDateTime();
return dateObject;
};
/**
* Use this function to make a date time from date string in an ISO format
* Please not that this function is limited to ISO 8601
* @param date
* @param option
*/
MagicDate.makeDateFromString = function (date, option) {
if (option === void 0) { option = {}; }
return new MagicDate(new Date(date), option);
};
/**
* A function to generate an Array of MagicDate objects from a reference start date to an end date
* @param start
* @param end
* @param abstraction
* @param weekStart
* @param includeEndDate
*/
MagicDate.getDateFromTo = function (start, end, abstraction, weekStart, includeEndDate) {
if (abstraction === void 0) { abstraction = "day"; }
if (weekStart === void 0) { weekStart = null; }
if (includeEndDate === void 0) { includeEndDate = true; }
var startNumeric = start.dtTime;
var endNumeric = end.dtTime;
// $weekStart = $weekStart || MagicDate.DEFAULT_WEEK_START;
var dateArray = [];
// check if date is in correct order and throw exception if not
if (!MagicDate.validateDatePosition(start, end))
throw new Error(MagicDate.EXCEPTIONS.dateRangeOrderException);
// a caveat to include end date when return a dates between 2 dates
var endDatePadding = includeEndDate ? MagicDate.timeMult(abstraction) : 0;
var i = startNumeric;
while (i && endNumeric && i < endNumeric + endDatePadding) {
var __dateObject = MagicDate.SIMPLE_DATE;
__dateObject.dt = i;
dateArray.push(MagicDate.makeDate(__dateObject));
i += MagicDate.timeMult(abstraction);
}
return dateArray;
};
/**
* A function to get first date of a given week number
* @param weekNum
* @param year
*/
MagicDate.getDateFromWeekNum = function (weekNum, year) {
var __dateObject = {};
__dateObject.year = year || new Date().getFullYear();
__dateObject.month = 1;
__dateObject.day = 1;
var dateObject = MagicDate.makeDate(__dateObject);
return dateObject.next(weekNum - 1 + " weeks").getWeekFirstDate();
};
/**
* A function to get an array of dates of a given week number
* @param weekNum
* @param year
* @param abstraction
* @param weekStart
* @param includeEndDate
*/
MagicDate.getDatesFromWeekNum = function (_a) {
var weekNum = _a.weekNum, _b = _a.year, year = _b === void 0 ? null : _b, _c = _a.abstraction, abstraction = _c === void 0 ? "day" : _c, _d = _a.weekStart, weekStart = _d === void 0 ? MagicDate.DEFAULT_WEEK_START : _d, _e = _a.includeEndDate, includeEndDate = _e === void 0 ? false : _e;
var start = MagicDate.getDateFromWeekNum(weekNum, year);
var end = MagicDate.getDateFromWeekNum(weekNum, year).getWeekLastDate();
return MagicDate.getDateFromTo(start, end, abstraction, weekStart, includeEndDate);
};
/**
* Will return an array of weeks
* @param $range
* @param $start
* @param $startYear
*/
MagicDate.getWeeks = function ($range, $start, $startYear) {
if ($range === void 0) { $range = 1; }
var dateObject = new MagicDate();
$start = $start || dateObject.weeknum || 0;
var weekArray = [];
var year = $startYear || dateObject.year || new Date().getFullYear();
var weekNum = $start;
var i = 0;
while (i < $range) {
if (weekNum === 52) {
year++;
weekNum = 1;
}
weekArray.push({ year: year, weekNum: weekNum });
weekNum++;
i++;
}
return weekArray;
};
/**
* A function to get the first date of a given month
* @param dateObject
* @param month
* @param year
*/
MagicDate.getMonthFirstDate = function (_a) {
var dateObject = _a.dateObject, month = _a.month, year = _a.year;
if (dateObject || (month && year)) {
if (dateObject) {
// @ts-ignore
month = dateObject.month;
// @ts-ignore
year = dateObject.year;
}
var __simpleDate = {
year: year,
month: month,
day: 1
};
return MagicDate.makeDate(__simpleDate);
}
else {
throw new Error(MagicDate.EXCEPTIONS.valueException);
}
};
/**
* A function to get the last date of a given month
* @param dateObject
* @param month
* @param year
*/
MagicDate.getMonthLastDate = function (_a) {
var dateObject = _a.dateObject, month = _a.month, year = _a.year;
if (dateObject || (month && year)) {
if (dateObject) {
// @ts-ignore
month = dateObject.month;
// @ts-ignore
year = dateObject.year;
}
var __simpleDate = {
year: year,
month: month,
day: MagicDate.getMonthLength(year, month)
};
return MagicDate.makeDate(__simpleDate);
}
else {
throw new Error(MagicDate.EXCEPTIONS.valueException);
}
};
/**
* A function to return the length of any given month and year
* @param year
* @param month
*/
MagicDate.getMonthLength = function (year, month) {
var __monthLabel = MagicDate.MONTHS[month - 1];
return MagicDate.isLeapYear(year) ? __monthLabel.length + 1 : __monthLabel.length;
};
/**
* A boolean function to check the positions of 2 dates,
* will return false if (a, b) a date is greater than b date
* @param a
* @param b
*/
MagicDate.validateDatePosition = function (a, b) {
var __dateObjectA = MagicDate.SIMPLE_DATE;
__dateObjectA.dt = a;
var __dateObjectB = MagicDate.SIMPLE_DATE;
__dateObjectB.dt = b;
return MagicDate.makeDate(__dateObjectA).dtTime <= MagicDate.makeDate(__dateObjectB).dtTime;
};
MagicDate.validateDateConfig = function (value, type) {
var __dateObject = MagicDate.SIMPLE_DATE;
value = value || __dateObject[value];
if (value < MagicDate.CONFIG_BOUNDARIES[type + "_boundary"][0] ||
value > MagicDate.CONFIG_BOUNDARIES[type + "_boundary"][1]) {
return "The argument entered for " + type + ": " + value + " is out of the MagicDate scope";
}
return null;
};
/**
* Make a timezone iso string
* @param timezoneOffset
* @param dtObj
*/
MagicDate.makeTimezoneStr = function (timezoneOffset, dtObj) {
if (timezoneOffset === void 0) { timezoneOffset = null; }
if (dtObj === void 0) { dtObj = null; }
var _timezoneOffset = timezoneOffset || (dtObj === null || dtObj === void 0 ? void 0 : dtObj.getTimezoneOffset()) || new Date().getTimezoneOffset();
var minutes = Math.abs(_timezoneOffset / 60);
var paddedMinutes = MagicDate.padding(minutes.toString(), 2, "0");
var sign = _timezoneOffset < 0 ? "+" : "-";
return "" + sign + paddedMinutes + ":00";
};
/**
* Check if current year is a leap
* @param year
*/
MagicDate.isLeapYear = function (year) {
return year % 4 === 0;
};
MagicDate.timeMult = function (type) {
// ms in a week, day, hour, min, sec
switch (type) {
case "week":
return 7 * 24 * 60 * 60 * 1000;
case "day":
return 24 * 60 * 60 * 1000;
case "hour":
return 60 * 60 * 1000;
case "min":
return 60 * 1000;
case "sec":
return 1000;
}
return 0;
};
MagicDate.padding = function (value, len, paddingStr) {
len = len - value.length + 1;
return len > 0 ? new Array(len).join(paddingStr) + value : value;
};
/**
* Generate current time
*/
MagicDate.prototype.now = function (date) {
if (date === void 0) { date = null; }
this.dtObj = date || new Date();
this._toNumber()._analyseDateTime();
return this;
};
/**
* Get todays date
*/
MagicDate.prototype.today = function (date) {
if (date === void 0) { date = null; }
(date === null || date === void 0 ? void 0 : date.getDate()) || (this.dtObj && this.dtObj.getDate());
return this;
};
/**
* Get the first date of the week
*/
MagicDate.prototype.getWeekFirstDate = function () {
this.next("-" + this.weekdayNumeric + " days");
return this;
};
/**
* Last date of a week
*/
MagicDate.prototype.getWeekLastDate = function () {
this.weekdayNumeric !== null && this.next(6 - this.weekdayNumeric + " days");
return this;
};
/**
* The first date in the month
*/
MagicDate.prototype.getMonthFirstDate = function () {
return MagicDate.getMonthFirstDate({ dateObject: this });
};
/**
* The last date of the month
*/
MagicDate.prototype.getMonthLastDate = function () {
return MagicDate.getMonthLastDate({ dateObject: this });
};
/**
* Get the current week number
*/
MagicDate.prototype.getWeekNum = function () {
this.year = this.year || new Date().getFullYear();
var januaryFirst = new Date(this.year, 0, 1);
var v = (this.dtTime || 0) / MagicDate.timeMult(MagicDate.LABELS.day) -
januaryFirst.getTime() / MagicDate.timeMult(MagicDate.LABELS.day) +
januaryFirst.getDay() -
(this.weekStart.name === MagicDate.DEFAULT_WEEK_START.name ? 1 : 0);
return Math.floor(v / 7) + 1;
};
/**
* Set when the week starts
* @param weekStartInt i.e. 0>>Sunday, 1>>Monday
*/
MagicDate.prototype.setWeekStart = function (weekStartInt) {
this.weekStart = MagicDate.WEEKDAYS[weekStartInt] || MagicDate.DEFAULT_WEEK_START;
return this;
};
/**
* A generic command to increment dates, months and yeara
* e.g.
* 1. <MagicDate>.next("1 month")
* 2. <MagicDate>.next("-1 days") (will substract from the current date)
* @param command
*/
MagicDate.prototype.next = function (command) {
var _a = command.split(" "), value = _a[0], abstraction = _a[1];
var valueInt = parseInt(value);
var polarity = valueInt >= 0 ? 1 : -1;
// 3 years, 4 months, 2 weeks, 7 days, 1 month, 5 weeks, 1 hour, 4 minutes, 32
// seconds
abstraction =
abstraction.substr(-1, 1) === "s"
? abstraction.substring(0, abstraction.length - 1)
: abstraction;
// normalize the minute and second entry to conform to out nomenclature
switch (abstraction) {
case "minute":
abstraction = "min";
break;
case "second":
abstraction = "sec";
break;
}
// this have irregular lengths so we will handle differently
if (["year", "month"].indexOf(abstraction) > -1) {
var yearDelta = 0, monthDelta = 0;
valueInt = Math.abs(valueInt);
switch (abstraction) {
case "year":
yearDelta = valueInt * polarity;
break;
case "month":
yearDelta = Math.floor(valueInt / 12) * polarity;
monthDelta = (valueInt % 12) * polarity;
break;
default:
}
var __simpleDate = MagicDate.SIMPLE_DATE;
__simpleDate.year = (this.year || new Date().getFullYear()) + yearDelta;
__simpleDate.month = (this.month || new Date().getMonth() + 1) + monthDelta; // month return a unit before in js
__simpleDate.day = this.day || new Date().getDay();
var monthLength = MagicDate.getMonthLength(__simpleDate.year, __simpleDate.month);
// correct date based on month length - e.g. if 31 appears on a November, will
// be changed to 30
if (monthLength < (this.day || new Date().getDay())) {
__simpleDate.day = monthLength;
}
return MagicDate.makeDate(__simpleDate);
}
else {
this.dtTime = this.dtTime && this.dtTime + valueInt * MagicDate.timeMult(abstraction);
}
this._formatFromNumericTime()._analyseDateTime();
return this;
};
/**
* Cast potential final outcome via a template e.g. "%Y-%m-%d"
* @param mask
*/
MagicDate.prototype.setCast = function (mask) {
this._castMask = mask;
return this;
};
/**
* Render the values of this class
*/
MagicDate.prototype.toString = function () {
this._formatWithLeadingZeroes();
var _a = this, yearStr = _a.yearStr, monthStr = _a.monthStr, dayStr = _a.dayStr, hourStr = _a.hourStr, minuteStr = _a.minuteStr, secondStr = _a.secondStr, microSecondStr = _a.microSecondStr, timezoneStr = _a.timezoneStr;
if (this._castMask) {
var __ret_1 = this._castMask;
var keywords = __ret_1.match(/[A-Za-z]/g);
keywords &&
keywords.map(function (k) {
return (__ret_1 = __ret_1.replace("%" + k, eval(MagicDate.MASK_DICTIONARY[k] + "Str")));
});
return __ret_1;
}
return yearStr + "-" + monthStr + "-" + dayStr + " " + hourStr + ":" + minuteStr + ":" + secondStr + "." + microSecondStr + timezoneStr;
};
/**
* Boiler plater rendered, renders a date string
*/
MagicDate.prototype.toDateString = function () {
this._castMask = "%Y-%m-%d";
return this.toString();
};
/**
* Boiler plater rendered, renders a time string
*/
MagicDate.prototype.toTimeString = function () {
this._castMask = "%H:%i:%s";
return this.toString();
};
/**
* Check if current year is a leap year
*/
MagicDate.prototype.isLeapYear = function () {
return MagicDate.isLeapYear(this.year || new Date().getFullYear());
};
MagicDate.prototype._toNumber = function () {
var _dt = this.dtObj &&
this.dtObj.getTime() +
-1 * new Date().getTimezoneOffset() * MagicDate.timeMult("min") -
1000 * 60;
if (_dt) {
this.dtObj = new Date(_dt);
this.dtTime = this.dtObj.getTime();
}
return this;
};
MagicDate.prototype._formatFromNumericTime = function () {
this.dtObj = new Date(this.dtTime);
return this;
};
MagicDate.prototype._formatWithLeadingZeroes = function () {
var _a = this, year = _a.year, month = _a.month, day = _a.day, hour = _a.hour, minute = _a.minute, second = _a.second, microSecond = _a.microSecond;
this.yearStr = (year === null || year === void 0 ? void 0 : year.toString()) || null;
this.monthStr = (month !== null && MagicDate.padding(month.toString(), 2, "0")) || null;
this.dayStr = (day !== null && MagicDate.padding(day.toString(), 2, "0")) || null;
this.hourStr = (hour !== null && MagicDate.padding(hour.toString(), 2, "0")) || null;
this.minuteStr = (minute !== null && MagicDate.padding(minute.toString(), 2, "0")) || null;
this.secondStr = (second !== null && MagicDate.padding(second.toString(), 2, "0")) || null;
this.microSecondStr =
(microSecond !== null &&
MagicDate.padding(microSecond.toString(), this.options.microSecondsLength || MagicDate.DEFAULT_MICRO_SECONDS_LENGTH, "0")) ||
null;
return this;
};
MagicDate.prototype._analyseDateTime = function () {
try {
if (this.dtObj) {
var isoDate = this.dtObj.toISOString();
this.weekdayNumeric = this.dtObj.getDay();
this.weekday = MagicDate.WEEKDAYS[this.weekdayNumeric];
this.year = parseInt(isoDate.substring(0, 4));
this.month = parseInt(isoDate.substring(5, 7));
this.day = parseInt(isoDate.substring(8, 10));
this.hour = parseInt(isoDate.substring(11, 13));
this.minute = parseInt(isoDate.substring(14, 16));
this.second = parseInt(isoDate.substring(17, 19));
this.microSecond = parseInt(isoDate.substring(20, 23));
this.timezoneStr = MagicDate.makeTimezoneStr(this.timezoneOffset, this.dtObj);
this.weeknum = this.getWeekNum();
this.leapYear = this.year % 4 === 0;
switch (this.options.dateIso) {
case TimeFormat.ISO8601:
default:
this._castMask = "%Y-%m-%d %H:%i:%s.%u%t";
}
this._formatWithLeadingZeroes();
return this;
}
}
catch (e) {
console.error(e);
}
return this;
};
/**
* Dictionary of month definitions
*/
MagicDate.MONTHS = [
{
code: "01",
shortName: "Jan",
length: 31,
name: "January"
},
{
code: "02",
shortName: "Feb",
length: 28,
name: "February"
},
{
code: "03",
shortName: "Mar",
length: 31,
name: "March"
},
{
code: "04",
shortName: "Apr",
length: 30,
name: "April"
},
{
code: "05",
shortName: "May",
length: 31,
name: "May"
},
{
code: "06",
shortName: "Jun",
length: 30,
name: "June"
},
{
code: "07",
shortName: "Jul",
length: 31,
name: "July"
},
{
code: "08",
shortName: "Aug",
length: 31,
name: "August"
},
{
code: "09",
shortName: "Sep",
length: 30,
name: "September"
},
{
code: "10",
shortName: "Oct",
length: 31,
name: "October"
},
{
code: "11",
shortName: "Nov",
length: 30,
name: "November"
},
{
code: "12",
shortName: "Dec",
length: 31,
name: "December"
}
];
/**
* Dictionary of weekday definitions
*/
MagicDate.WEEKDAYS = [
{
code: "01",
shortName: "Sun",
name: "Sunday"
},
{
code: "02",
shortName: "Mon",
name: "Monday"
},
{
code: "03",
shortName: "Tue",
name: "Tuesday"
},
{
code: "04",
shortName: "Wed",
name: "Wednesday"
},
{
code: "05",
shortName: "Thu",
name: "Thursday"
},
{
code: "06",
shortName: "Fri",
name: "Friday"
},
{
code: "07",
shortName: "Sat",
name: "Saturday"
}
];
/**
* Default start date of the week
*/
MagicDate.DEFAULT_WEEK_START = MagicDate.WEEKDAYS[0];
MagicDate.DEFAULT_MICRO_SECONDS_LENGTH = 6;
MagicDate.DEFAULT_ISO_FORMAT = TimeFormat.ISO8601;
/**
* Boundaries for configuration
*/
MagicDate.CONFIG_BOUNDARIES = {
year_boundary: [1900, 2100],
month_boundary: [1, 12],
day_boundary: [1, 31],
hour_boundary: [0, 23],
min_boundary: [0, 59],
sec_boundary: [0, 59],
microSecond_boundary: [0, 999999]
};
/**
* Generic labels
*/
MagicDate.LABELS = {
day: "day"
};
/**
* Mask dictionary for date variables
*/
MagicDate.MASK_DICTIONARY = {
Y: "year",
m: "month",
d: "day",
H: "hour",
i: "minute",
s: "second",
u: "microSecond",
t: "timezone"
};
/**
* Default date structure
*/
MagicDate.SIMPLE_DATE = {
dt: null,
year: null,
month: null,
day: null,
hour: 12,
min: 0,
sec: 0,
microSecond: 0,
timezoneOffset: 0
};
/**
* Exception dictionary
*/
MagicDate.EXCEPTIONS = {
dateRangeOrderException: "You tried to get an array of dates between 2 dates, but the start date selected " +
"seems to be ahead of the end date",
valueException: "Argument parsed failed to process"
};
return MagicDate;
}());
exports["default"] = MagicDate;