UNPKG

@simonbluhm/timely

Version:

working with date and time in javascript

231 lines (229 loc) 9 kB
function stringToArray(value) { if (!value) return {}; let year, month, day, hrs, min, sec; const separator = value.replace(/[A-Za-z0-9]/g, '')[0]; if (separator === ':') { [hrs, min = 0, sec = 0] = value.split(separator).map((i) => +i); return { hrs, min, sec }; } else { const arr = value.split(separator); year = arr[0].length === 4 ? +arr[0] : +arr[2]; day = arr[0].length === 2 ? +arr[0] : +arr[2]; month = +arr[1]; return { year, month, day }; } } function parseDateTime(value, format) { switch (format) { default: const [date, time] = value.split(' '); const { year, month, day } = stringToArray(date); const { hrs = 0, min = 0, sec = 0 } = stringToArray(time); return new Date(+year, +month - 1, +day, +hrs, +min, +sec); } } function parseDateArgument(date, format) { if (date instanceof Date) { return new Date(+date); } else if (Array.isArray(date)) { const [YYYY, MM = 0, DD = 1, HH = 0, mm = 0, ss = 0] = date; return new Date(YYYY, MM, DD, HH, mm, ss); } else if (typeof date === 'number') { return new Date(date); } else if (date.split('T').length === 2) { return new Date(date); } else { return parseDateTime(date, format); } } class Timely { constructor(date = new Date(), format = null, locale = 'en-GB') { this._locale = locale; this._timeZone = null; this._UTC = false; this._date = parseDateArgument(date, format); } setTime(hrs, min = 0, sec = 0, msec = 0) { this._date.setHours(+hrs, +min, +sec, +msec); return this; } setDate(year, month = 0, day = 1) { this._date.setFullYear(+year, +month, +day); return this; } subtract(value, units = 'days') { if (units == 'days') this._date.setDate(this._date.getDate() - value); else if (units == 'months') this._date.setMonth(this._date.getMonth() - value); else if (units == 'years') this._date.setFullYear(this._date.getFullYear() - value); else throw new Error('Unknown units'); return this; } add(value, units = 'days') { if (units == 'days') this._date.setDate(this._date.getDate() + value); else if (units == 'months') this._date.setMonth(this._date.getMonth() + value); else if (units == 'years') this._date.setFullYear(this._date.getFullYear() + value); else throw new Error('Unknown units'); return this; } timeZone(zone) { this._timeZone = zone; return this; } instance() { return this._date; } format(format = 'Date') { const values = this._timeZone === 'UTC' ? [ this._date.getUTCDate(), this._date.getUTCMonth() + 1, this._date.getUTCFullYear(), this._date.getUTCHours(), this._date.getUTCMinutes(), this._date.getUTCSeconds(), ] : [ this._date.getDate(), this._date.getMonth() + 1, this._date.getFullYear(), this._date.getHours(), this._date.getMinutes(), this._date.getSeconds(), ]; const [day, month, year, hrs, min, sec] = values.map((item) => item.toString().padStart(2, '0')); switch (format) { case 'DateTime': return year + '-' + month + '-' + day + ' ' + hrs + ':' + min + ':' + sec; case 'Date': return year + '-' + month + '-' + day; case 'Time': return hrs + ':' + min + ':' + sec; case 'HoursMinutes': return hrs + ':' + min; case 'YearMonth': return year + '-' + month; case 'MonthDay': return month + '-' + day; case 'Month': return parseInt(month); case 'Array': return [this._date.getFullYear(), this._date.getMonth() + 1, this._date.getDate()]; case 'dd/MM/yyyy': return day + '/' + month + '/' + year; default: return null; } } locale(format = 'ShortMonth') { const timeZone = this._timeZone ? this._timeZone : Intl.DateTimeFormat().resolvedOptions().timeZone; const present = new Date('2100-01-01'); if (this._date.getTime() == present.getTime()) return 'Present'; const NUMERIC = 'numeric'; const LONG = 'long'; const SHORT = 'short'; const DIGIT = '2-digit'; const year = NUMERIC; const weekday = LONG; const hour = DIGIT; const minute = DIGIT; switch (format) { case 'Time': return this._date.toLocaleTimeString(this._locale, { timeZone }); case 'Date': return this._date.toLocaleDateString(this._locale, { year, month: DIGIT, day: DIGIT }); case 'DateTime': return this._date.toLocaleDateString(this._locale, { year, month: DIGIT, day: DIGIT, hour, minute }); case 'LongDate': return this._date.toLocaleDateString(this._locale, { year, weekday, month: LONG, day: NUMERIC }); case 'ShortDate': return this._date.toLocaleDateString(this._locale, { year, month: SHORT, day: NUMERIC }); case '1.1': return this._date.toLocaleDateString(this._locale, { month: NUMERIC, day: NUMERIC }); case '1 Jan': return this._date.toLocaleDateString(this._locale, { month: SHORT, day: NUMERIC }); case 'DateWithLongMonth': return this._date.toLocaleDateString(this._locale, { year, month: LONG, day: NUMERIC }); case 'LongDayAndMonth': return this._date.toLocaleDateString(this._locale, { weekday, month: LONG, day: NUMERIC }); case 'ShortMonth': return this._date.toLocaleDateString(this._locale, { month: SHORT }); case 'ShortMonthYear': return this._date.toLocaleDateString(this._locale, { month: SHORT, year }); case 'LongMonthYear': return this._date.toLocaleDateString(this._locale, { month: LONG, year }); default: return null; } } toString() { return this._date.toISOString(); } year() { return this._date.getFullYear(); } month(format = 'index') { return format === 'index' ? this._date.getMonth() : this._date.toLocaleString(this._locale, { month: format }); } day() { return this._date.getDate(); } weekday(format = 'index') { const dt = this._date; return format === 'index' ? dt.getDay() : dt.toLocaleString(this._locale, { weekday: format }); } weekNumber() { const dt = new Date(Date.UTC(this._date.getFullYear(), this._date.getMonth(), this._date.getDate())); dt.setUTCDate(dt.getUTCDate() + 4 - (dt.getUTCDay() || 7)); const firstDayOfYear = new Date(Date.UTC(dt.getUTCFullYear(), 0, 1)); const oneDay = 86400000; const weekNo = Math.ceil(((dt.getTime() - firstDayOfYear.getTime()) / oneDay + 1) / 7); return [dt.getUTCFullYear(), weekNo]; } timestamp() { return this._date.getTime(); } diff(date, units = 'hrs') { const _date = parseDateArgument(date); const diff = this._date.getTime() - _date.getTime(); const parseUnits = { sec: 1000, min: 60 * 1000, hrs: 60 * 60 * 1000, days: 24 * 60 * 60 * 1000, }; const TIME_UNITS = parseUnits[units]; if (TIME_UNITS === undefined) throw new Error('No time units found'); return Math.floor(Math.abs(diff / TIME_UNITS)); } isEqual(date) { const _date = parseDateArgument(date); return (this._date.getFullYear() === _date.getFullYear() && this._date.getMonth() === _date.getMonth() && this._date.getDate() === _date.getDate()); } isLeapYear(year) { return year % 100 === 0 ? (year % 400 === 0 ? true : false) : year % 4 === 0; } daysInMonth() { const year = this._date.getFullYear(); const month = this._date.getMonth(); return [31, this.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; } } export default Timely;