Eduard Kuzmenko
4 years ago
23 changed files with 568 additions and 119 deletions
@ -0,0 +1,381 @@
@@ -0,0 +1,381 @@
|
||||
/* |
||||
* Date Format 1.2.3 |
||||
* (c) 2007-2009 Steven Levithan <stevenlevithan.com> |
||||
* MIT license |
||||
* |
||||
* Includes enhancements by Scott Trenda <scott.trenda.net> |
||||
* and Kris Kowal <cixar.com/~kris.kowal/> |
||||
* |
||||
* Accepts a date, a mask, or a date and a mask. |
||||
* Returns a formatted version of the given date. |
||||
* The date defaults to the current date/time. |
||||
* The mask defaults to dateFormat.masks.default. |
||||
*/ |
||||
|
||||
const dateFormat = (() => { |
||||
const token = /d{1,4}|D{3,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|W{1,2}|[LlopSZN]|"[^"]*"|'[^']*'/g; |
||||
const timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g; |
||||
const timezoneClip = /[^-+\dA-Z]/g; |
||||
|
||||
// Regexes and supporting functions are cached through closure
|
||||
function f(date?: number | Date, mask?: string, utc?: boolean, gmt?: boolean): string { |
||||
// You can't provide utc if you skip other args (use the 'UTC:' mask prefix)
|
||||
/* if( |
||||
arguments.length === 1 && |
||||
kindOf(date) === "string" && |
||||
!/\d/.test(date) |
||||
) { |
||||
mask = date; |
||||
date = undefined; |
||||
} */ |
||||
|
||||
date = date || date === 0 ? date : new Date(); |
||||
|
||||
if(!(date instanceof Date)) { |
||||
date = new Date(date); |
||||
} |
||||
|
||||
/* if(isNaN(date)) { |
||||
throw TypeError("Invalid date"); |
||||
} */ |
||||
|
||||
/* mask = String( |
||||
dateFormat.masks[mask] || mask || dateFormat.masks["default"] |
||||
); */ |
||||
|
||||
// Allow setting the utc/gmt argument via the mask
|
||||
const maskSlice = mask.slice(0, 4); |
||||
if(maskSlice === "UTC:" || maskSlice === "GMT:") { |
||||
mask = mask.slice(4); |
||||
utc = true; |
||||
if(maskSlice === "GMT:") { |
||||
gmt = true; |
||||
} |
||||
} |
||||
|
||||
const _ = () => (utc ? "getUTC" : "get"); |
||||
const d = (): number => (date as any)[_() + "Date"](); |
||||
const D = (): number => (date as any)[_() + "Day"](); |
||||
const m = (): number => (date as any)[_() + "Month"](); |
||||
const y = (): number => (date as any)[_() + "FullYear"](); |
||||
const H = (): number => (date as any)[_() + "Hours"](); |
||||
const M = (): number => (date as any)[_() + "Minutes"](); |
||||
const s = (): number => (date as any)[_() + "Seconds"](); |
||||
const L = (): number => (date as any)[_() + "Milliseconds"](); |
||||
const o = (): number => (utc ? 0 : (date as Date).getTimezoneOffset()); |
||||
const W = (): number => getWeek(date as Date); |
||||
const N = (): number => getDayOfWeek(date as Date); |
||||
|
||||
const flags = { |
||||
d: () => d(), |
||||
dd: () => pad(d()), |
||||
ddd: () => dateFormat.i18n.dayNames[D()], |
||||
DDD: () => getDayName({ |
||||
y: y(), |
||||
m: m(), |
||||
d: d(), |
||||
_: _(), |
||||
dayName: dateFormat.i18n.dayNames[D()], |
||||
short: true |
||||
}), |
||||
dddd: () => dateFormat.i18n.dayNames[D() + 7], |
||||
DDDD: () => getDayName({ |
||||
y: y(), |
||||
m: m(), |
||||
d: d(), |
||||
_: _(), |
||||
dayName: dateFormat.i18n.dayNames[D() + 7] |
||||
}), |
||||
m: () => m() + 1, |
||||
mm: () => pad(m() + 1), |
||||
mmm: () => dateFormat.i18n.monthNames[m()], |
||||
mmmm: () => dateFormat.i18n.monthNames[m() + 12], |
||||
yy: () => String(y()).slice(2), |
||||
yyyy: () => pad(y(), 4), |
||||
h: () => H() % 12 || 12, |
||||
hh: () => pad(H() % 12 || 12), |
||||
H: () => H(), |
||||
HH: () => pad(H()), |
||||
M: () => M(), |
||||
MM: () => pad(M()), |
||||
s: () => s(), |
||||
ss: () => pad(s()), |
||||
l: () => pad(L(), 3), |
||||
L: () => pad(Math.floor(L() / 10)), |
||||
t: () => |
||||
H() < 12 ? |
||||
dateFormat.i18n.timeNames[0] : dateFormat.i18n.timeNames[1], |
||||
tt: () => |
||||
H() < 12 ? |
||||
dateFormat.i18n.timeNames[2] : dateFormat.i18n.timeNames[3], |
||||
T: () => |
||||
H() < 12 ? |
||||
dateFormat.i18n.timeNames[4] : dateFormat.i18n.timeNames[5], |
||||
TT: () => |
||||
H() < 12 ? |
||||
dateFormat.i18n.timeNames[6] : dateFormat.i18n.timeNames[7], |
||||
Z: () => |
||||
gmt ? |
||||
"GMT" : utc ? |
||||
"UTC" : (String(date).match(timezone) || [""]) |
||||
.pop() |
||||
.replace(timezoneClip, "") |
||||
.replace(/GMT\+0000/g, "UTC"), |
||||
o: () => |
||||
(o() > 0 ? "-" : "+") + |
||||
pad(Math.floor(Math.abs(o()) / 60) * 100 + (Math.abs(o()) % 60), 4), |
||||
p: () => |
||||
(o() > 0 ? "-" : "+") + |
||||
pad(Math.floor(Math.abs(o()) / 60), 2) + |
||||
":" + |
||||
pad(Math.floor(Math.abs(o()) % 60), 2), |
||||
S: () => ["th", "st", "nd", "rd"][ |
||||
// @ts-ignore
|
||||
d() % 10 > 3 ? 0 : (((d() % 100) - (d() % 10) != 10) * d()) % 10 |
||||
], |
||||
W: () => W(), |
||||
WW: () => pad(W()), |
||||
N: () => N(), |
||||
}; |
||||
|
||||
return mask.replace(token, (match) => { |
||||
if(match in flags) { |
||||
// @ts-ignore
|
||||
return flags[match](); |
||||
} |
||||
return match.slice(1, match.length - 1); |
||||
}); |
||||
}; |
||||
|
||||
// Internationalization strings
|
||||
f.i18n = { |
||||
dayNames: [ |
||||
"Sun", |
||||
"Mon", |
||||
"Tue", |
||||
"Wed", |
||||
"Thu", |
||||
"Fri", |
||||
"Sat", |
||||
"Sunday", |
||||
"Monday", |
||||
"Tuesday", |
||||
"Wednesday", |
||||
"Thursday", |
||||
"Friday", |
||||
"Saturday", |
||||
], |
||||
monthNames: [ |
||||
"Jan", |
||||
"Feb", |
||||
"Mar", |
||||
"Apr", |
||||
"May", |
||||
"Jun", |
||||
"Jul", |
||||
"Aug", |
||||
"Sep", |
||||
"Oct", |
||||
"Nov", |
||||
"Dec", |
||||
"January", |
||||
"February", |
||||
"March", |
||||
"April", |
||||
"May", |
||||
"June", |
||||
"July", |
||||
"August", |
||||
"September", |
||||
"October", |
||||
"November", |
||||
"December", |
||||
], |
||||
timeNames: ["a", "p", "am", "pm", "A", "P", "AM", "PM"], |
||||
}; |
||||
|
||||
f.setLocale = function(code: string) { |
||||
const date = new Date(); |
||||
|
||||
{ |
||||
const dateTimeFormat = new Intl.DateTimeFormat(code, {month: 'long'}); |
||||
const dateTimeFormatShort = new Intl.DateTimeFormat(code, {month: 'short'}); |
||||
for(let i = 0; i < 12; ++i) { |
||||
date.setMonth(i); |
||||
f.i18n.monthNames[i] = dateTimeFormatShort.format(date); |
||||
f.i18n.monthNames[i + 12] = dateTimeFormat.format(date); |
||||
} |
||||
} |
||||
|
||||
{ |
||||
const day = date.getDay(); |
||||
if(day !== 0) { |
||||
date.setDate(date.getDate() - day); |
||||
} |
||||
|
||||
const dateTimeFormat = new Intl.DateTimeFormat(code, {weekday: 'long'}); |
||||
const dateTimeFormatShort = new Intl.DateTimeFormat(code, {weekday: 'short'}); |
||||
for(let i = 0; i < 7; ++i) { |
||||
date.setDate(date.getDate() + 1); |
||||
f.i18n.dayNames[i] = dateTimeFormatShort.format(date); |
||||
f.i18n.dayNames[i + 7] = dateTimeFormat.format(date); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
return f; |
||||
})(); |
||||
|
||||
export default dateFormat; |
||||
|
||||
(window as any).dateFormat = dateFormat; |
||||
|
||||
/* dateFormat.masks = { |
||||
default: "ddd mmm dd yyyy HH:MM:ss", |
||||
shortDate: "m/d/yy", |
||||
paddedShortDate: "mm/dd/yyyy", |
||||
mediumDate: "mmm d, yyyy", |
||||
longDate: "mmmm d, yyyy", |
||||
fullDate: "dddd, mmmm d, yyyy", |
||||
shortTime: "h:MM TT", |
||||
mediumTime: "h:MM:ss TT", |
||||
longTime: "h:MM:ss TT Z", |
||||
isoDate: "yyyy-mm-dd", |
||||
isoTime: "HH:MM:ss", |
||||
isoDateTime: "yyyy-mm-dd'T'HH:MM:sso", |
||||
isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'", |
||||
expiresHeaderFormat: "ddd, dd mmm yyyy HH:MM:ss Z", |
||||
}; */ |
||||
|
||||
const pad = (val: number | string, len = 2) => { |
||||
val = String(val); |
||||
while(val.length < len) { |
||||
val = "0" + val; |
||||
} |
||||
return val; |
||||
}; |
||||
|
||||
/** |
||||
* Get day name |
||||
* Yesterday, Today, Tomorrow if the date lies within, else fallback to Monday - Sunday |
||||
* @param {Object} |
||||
* @return {String} |
||||
*/ |
||||
const getDayName = ({ |
||||
y, |
||||
m, |
||||
d, |
||||
_, |
||||
dayName, |
||||
short = false |
||||
}: { |
||||
y: number, |
||||
m: number, |
||||
d: number, |
||||
_: any, |
||||
dayName: any, |
||||
short?: boolean |
||||
}) => { |
||||
const today = new Date(); |
||||
const yesterday = new Date(); |
||||
yesterday.setDate((yesterday as any)[_ + 'Date']() - 1); |
||||
const tomorrow = new Date(); |
||||
tomorrow.setDate((tomorrow as any)[_ + 'Date']() + 1); |
||||
const today_d = (): number => (today as any)[_ + 'Date'](); |
||||
const today_m = (): number => (today as any)[_ + 'Month'](); |
||||
const today_y = (): number => (today as any)[_ + 'FullYear'](); |
||||
const yesterday_d = (): number => (yesterday as any)[_ + 'Date'](); |
||||
const yesterday_m = (): number => (yesterday as any)[_ + 'Month'](); |
||||
const yesterday_y = (): number => (yesterday as any)[_ + 'FullYear'](); |
||||
const tomorrow_d = (): number => (tomorrow as any)[_ + 'Date'](); |
||||
const tomorrow_m = (): number => (tomorrow as any)[_ + 'Month'](); |
||||
const tomorrow_y = (): number => (tomorrow as any)[_ + 'FullYear'](); |
||||
|
||||
if(today_y() === y && today_m() === m && today_d() === d) { |
||||
return short ? 'Tdy' : 'Today'; |
||||
} else if(yesterday_y() === y && yesterday_m() === m && yesterday_d() === d) { |
||||
return short ? 'Ysd' : 'Yesterday'; |
||||
} else if(tomorrow_y() === y && tomorrow_m() === m && tomorrow_d() === d) { |
||||
return short ? 'Tmw' : 'Tomorrow'; |
||||
} |
||||
return dayName; |
||||
}; |
||||
|
||||
/** |
||||
* Get the ISO 8601 week number |
||||
* Based on comments from |
||||
* http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
|
||||
* |
||||
* @param {Object} `date` |
||||
* @return {Number} |
||||
*/ |
||||
const getWeek = (date: Date) => { |
||||
// Remove time components of date
|
||||
const targetThursday = new Date( |
||||
date.getFullYear(), |
||||
date.getMonth(), |
||||
date.getDate() |
||||
); |
||||
|
||||
// Change date to Thursday same week
|
||||
targetThursday.setDate( |
||||
targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3 |
||||
); |
||||
|
||||
// Take January 4th as it is always in week 1 (see ISO 8601)
|
||||
const firstThursday = new Date(targetThursday.getFullYear(), 0, 4); |
||||
|
||||
// Change date to Thursday same week
|
||||
firstThursday.setDate( |
||||
firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3 |
||||
); |
||||
|
||||
// Check if daylight-saving-time-switch occurred and correct for it
|
||||
const ds = |
||||
targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset(); |
||||
targetThursday.setHours(targetThursday.getHours() - ds); |
||||
|
||||
// Number of weeks between target Thursday and first Thursday
|
||||
const weekDiff = (targetThursday.getTime() - firstThursday.getTime()) / (86400000 * 7); |
||||
return 1 + Math.floor(weekDiff); |
||||
}; |
||||
|
||||
/** |
||||
* Get ISO-8601 numeric representation of the day of the week |
||||
* 1 (for Monday) through 7 (for Sunday) |
||||
* |
||||
* @param {Object} `date` |
||||
* @return {Number} |
||||
*/ |
||||
const getDayOfWeek = (date: Date) => { |
||||
let dow = date.getDay(); |
||||
if(dow === 0) { |
||||
dow = 7; |
||||
} |
||||
return dow; |
||||
}; |
||||
|
||||
/** |
||||
* kind-of shortcut |
||||
* @param {*} val |
||||
* @return {String} |
||||
*/ |
||||
/* const kindOf = (val: any) => { |
||||
if(val === null) { |
||||
return "null"; |
||||
} |
||||
|
||||
if(val === undefined) { |
||||
return "undefined"; |
||||
} |
||||
|
||||
if(typeof val !== "object") { |
||||
return typeof val; |
||||
} |
||||
|
||||
if(Array.isArray(val)) { |
||||
return "array"; |
||||
} |
||||
|
||||
return {}.toString.call(val).slice(8, -1).toLowerCase(); |
||||
}; */ |
Loading…
Reference in new issue