@simonbluhm/timely
Version:
working with date and time in javascript
231 lines (229 loc) • 9 kB
JavaScript
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;