Skip to content

Commit cc2f815

Browse files
Vasil Raevggkrustev
authored andcommitted
feat: add dateFormatString function (#12)
* feat: add dateFormatString function, that returns full raw format depending on actual date date
1 parent 117fe1c commit cc2f815

File tree

6 files changed

+233
-197
lines changed

6 files changed

+233
-197
lines changed

src/dates.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ export function formatDate(value: Date, format: String|DateFormatOptions, locale
1919

2020
export function parseDate(value: string, format?: String|DateFormatOptions|Array<String>|Array<DateFormatOptions>, locale?: string): Date;
2121

22+
export function dateFormatString(value: Date, format: String|DateFormatOptions, locale?: string): string;

src/dates.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { default as formatDate } from './dates/format-date';
2-
export { default as parseDate } from './dates/parse-date';
2+
export { default as parseDate } from './dates/parse-date';
3+
export { default as dateFormatString } from './dates/date-format-string';

src/dates/date-format-string.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import dateGenericFormat from './date-generic-format';
2+
3+
export default function dateFormatString(date, format, locale = "en") {
4+
return dateGenericFormat(date, format, locale, true);
5+
}

src/dates/date-generic-format.js

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
import { localeInfo, firstDay } from '../cldr';
2+
import formatString from '../common/format-string';
3+
import datePattern from './date-pattern';
4+
import formatNames from './format-names';
5+
import pad from '../common/pad';
6+
import isDate from '../common/is-date';
7+
8+
const dateFormatRegExp = /d{1,2}|E{1,6}|e{1,6}|c{3,6}|c{1}|M{1,5}|L{1,5}|y{1,4}|H{1,2}|h{1,2}|m{1,2}|a{1,5}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|x{1,5}|X{1,5}|G{1,5}|q{1,5}|Q{1,5}|"[^"]*"|'[^']*'/g;
9+
10+
function formatDayOfWeekIndex(day, formatLength, localeInfo) {
11+
const firstDayIndex = firstDay(localeInfo);
12+
let dayIndex;
13+
if (day < firstDayIndex) {
14+
dayIndex = 7 - firstDayIndex + day;
15+
} else {
16+
dayIndex = day - firstDayIndex;
17+
}
18+
19+
return dayIndex + 1;
20+
}
21+
22+
function formatMonth(month, formatLength, info, standAlone) {
23+
if (formatLength <= 2) {
24+
return pad(month + 1, formatLength);
25+
}
26+
return formatNames(info, "months", formatLength, standAlone)[month];
27+
}
28+
29+
function formatQuarter(date, formatLength, info, standAlone) {
30+
const quarter = Math.floor(date.getMonth() / 3);
31+
if (formatLength < 3) {
32+
return quarter + 1;
33+
}
34+
35+
return formatNames(info, "quarters", formatLength, standAlone)[quarter];
36+
}
37+
38+
39+
function formatTimeZone(date, info, options) {
40+
const { shortHours, optionalMinutes, separator, localizedName, zZeroOffset } = options;
41+
const offset = date.getTimezoneOffset() / 60;
42+
if (offset === 0 && zZeroOffset) {
43+
return "Z";
44+
}
45+
const sign = offset <= 0 ? "+" : "-";
46+
const hoursMinutes = Math.abs(offset).toString().split(".");
47+
const minutes = hoursMinutes[1] || 0;
48+
let result = sign + (shortHours ? hoursMinutes[0] : pad(hoursMinutes[0], 2));
49+
if (minutes || !optionalMinutes) {
50+
result += (separator ? ":" : "") + pad(minutes, 2);
51+
}
52+
53+
if (localizedName) {
54+
const localizedFormat = offset === 0 ? info.calendar.gmtZeroFormat : info.calendar.gmtFormat;
55+
result = formatString(localizedFormat, result);
56+
}
57+
58+
return result;
59+
}
60+
function formatDayOfWeek(date, formatLength, info, standAlone) {
61+
let result;
62+
if (formatLength < 3) {
63+
result = formatDayOfWeekIndex(date.getDay(), formatLength, info);
64+
} else {
65+
result = formatNames(info, "days", formatLength, standAlone)[date.getDay()];
66+
}
67+
return result;
68+
}
69+
70+
71+
const formatters = {};
72+
73+
formatters.d = function(date, formatLength) {
74+
return pad(date.getDate(), formatLength);
75+
};
76+
77+
formatters.E = function(date, formatLength, info) {
78+
return formatNames(info, "days", formatLength)[date.getDay()];
79+
};
80+
81+
formatters.M = function(date, formatLength, info) {
82+
return formatMonth(date.getMonth(), formatLength, info, false);
83+
};
84+
85+
formatters.L = function(date, formatLength, info) {
86+
return formatMonth(date.getMonth(), formatLength, info, true);
87+
};
88+
89+
formatters.y = function(date, formatLength) {
90+
let year = date.getFullYear();
91+
if (formatLength === 2) {
92+
year = year % 100;
93+
}
94+
return pad(year, formatLength);
95+
};
96+
97+
formatters.h = function(date, formatLength) {
98+
const hours = date.getHours() % 12 || 12;
99+
return pad(hours, formatLength);
100+
};
101+
102+
formatters.H = function(date, formatLength) {
103+
return pad(date.getHours(), formatLength);
104+
};
105+
106+
formatters.m = function(date, formatLength) {
107+
return pad(date.getMinutes(), formatLength);
108+
};
109+
110+
formatters.s = function(date, formatLength) {
111+
return pad(date.getSeconds(), formatLength);
112+
};
113+
114+
formatters.S = function(date, formatLength) {
115+
const milliseconds = date.getMilliseconds();
116+
let result;
117+
if (milliseconds !== 0) {
118+
result = String(date.getMilliseconds() / 1000).split(".")[1].substr(0, formatLength);
119+
} else {
120+
result = pad("", formatLength);
121+
}
122+
return result;
123+
};
124+
125+
formatters.a = function(date, formatLength, info) {
126+
return formatNames(info, "dayPeriods", formatLength)[date.getHours() < 12 ? "am" : "pm"];
127+
};
128+
129+
formatters.z = function(date, formatLength, info) {
130+
return formatTimeZone(date, info, {
131+
shortHours: formatLength < 4,
132+
optionalMinutes: formatLength < 4,
133+
separator: true,
134+
localizedName: true
135+
});
136+
};
137+
138+
formatters.Z = function(date, formatLength, info) {
139+
return formatTimeZone(date, info, {
140+
separator: formatLength > 3,
141+
localizedName: formatLength === 4,
142+
zZeroOffset: formatLength === 5
143+
});
144+
};
145+
146+
formatters.x = function(date, formatLength, info) {
147+
return formatTimeZone(date, info, {
148+
optionalMinutes: formatLength === 1,
149+
separator: formatLength === 3 || formatLength === 5
150+
});
151+
};
152+
153+
formatters.X = function(date, formatLength, info) {
154+
return formatTimeZone(date, info, {
155+
optionalMinutes: formatLength === 1,
156+
separator: formatLength === 3 || formatLength === 5,
157+
zZeroOffset: true
158+
});
159+
};
160+
161+
formatters.G = function(date, formatLength, info) {
162+
let era = date.getFullYear() >= 0 ? 1 : 0;
163+
return formatNames(info, "eras", formatLength)[era];
164+
};
165+
166+
formatters.e = formatDayOfWeek;
167+
168+
formatters.c = function(date, formatLength, info) {
169+
return formatDayOfWeek(date, formatLength, info, true);
170+
};
171+
172+
formatters.q = function(date, formatLength, info) {
173+
return formatQuarter(date, formatLength, info, true);
174+
};
175+
176+
formatters.Q = formatQuarter;
177+
178+
export default function dateGenericFormat(date, format, locale = "en", returnPattern = false) {
179+
if (!isDate(date)) {
180+
return returnPattern ? format : date;
181+
}
182+
183+
const info = localeInfo(locale);
184+
const pattern = datePattern(format, info);
185+
186+
return pattern.replace(dateFormatRegExp, function(match) {
187+
let formatLength = match.length;
188+
let result;
189+
190+
if (match.includes("'") || match.includes("\"")) {
191+
result = match.slice(1, formatLength - 1);
192+
} else {
193+
result = formatters[match[0]](date, formatLength, info);
194+
195+
if (returnPattern) {
196+
let length = (result || "").toString().length;
197+
result = "";
198+
while (length > 0) {
199+
result += match[0];
200+
length--;
201+
}
202+
}
203+
}
204+
return result;
205+
});
206+
}

0 commit comments

Comments
 (0)