nmce-func 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/_func/addressFunc.d.ts +31 -31
- package/_func/authentication.service.d.ts +27 -27
- package/_func/currencyFunc.d.ts +20 -20
- package/_func/dateFunc.d.ts +121 -121
- package/_func/htmlPrintFunc.d.ts +18 -18
- package/_func/index.d.ts +10 -10
- package/_func/javascriptFunc.d.ts +10 -9
- package/_func/jsonFunc.d.ts +31 -31
- package/_func/stringAusFunc.d.ts +40 -40
- package/_func/stringFunc.d.ts +41 -41
- package/_func/uuidFunc.d.ts +7 -7
- package/{esm2020 → esm2022}/_func/addressFunc.mjs +48 -48
- package/esm2022/_func/authentication.service.mjs +48 -0
- package/esm2022/_func/currencyFunc.mjs +72 -0
- package/{esm2020 → esm2022}/_func/dateFunc.mjs +315 -315
- package/{esm2020 → esm2022}/_func/htmlPrintFunc.mjs +39 -39
- package/{esm2020 → esm2022}/_func/index.mjs +10 -10
- package/esm2022/_func/javascriptFunc.mjs +21 -0
- package/{esm2020 → esm2022}/_func/jsonFunc.mjs +66 -66
- package/esm2022/_func/stringAusFunc.mjs +200 -0
- package/{esm2020 → esm2022}/_func/stringFunc.mjs +92 -92
- package/{esm2020 → esm2022}/_func/uuidFunc.mjs +16 -16
- package/{esm2020 → esm2022}/nmce-func.mjs +4 -4
- package/{esm2020 → esm2022}/public-api.mjs +4 -4
- package/{fesm2020 → fesm2022}/nmce-func.mjs +902 -895
- package/{fesm2020 → fesm2022}/nmce-func.mjs.map +1 -1
- package/index.d.ts +5 -5
- package/package.json +5 -11
- package/public-api.d.ts +1 -1
- package/esm2020/_func/authentication.service.mjs +0 -45
- package/esm2020/_func/currencyFunc.mjs +0 -72
- package/esm2020/_func/javascriptFunc.mjs +0 -17
- package/esm2020/_func/stringAusFunc.mjs +0 -200
- package/fesm2015/nmce-func.mjs +0 -933
- package/fesm2015/nmce-func.mjs.map +0 -1
|
@@ -1,316 +1,316 @@
|
|
|
1
|
-
import moment from 'moment';
|
|
2
|
-
export class DateFunc {
|
|
3
|
-
/**
|
|
4
|
-
* Transform UTC DateTime to local date without H, M and S. For example, the month day of 2018-01-23T22:00:00Z is 24 in Australia.
|
|
5
|
-
* @param dtUtc
|
|
6
|
-
* @param offsetMinutes if not defined, it will be new Date().getTimezoneOffset(). //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
|
|
7
|
-
*/
|
|
8
|
-
static dateTimeUtcToLocalDateNumber(dtUtc) {
|
|
9
|
-
if (!dtUtc) {
|
|
10
|
-
return 0; //0 is better for calculation by the clients.
|
|
11
|
-
}
|
|
12
|
-
const localDt = DateFunc.dateTimeUtcToLocalDateTime(dtUtc);
|
|
13
|
-
const localDNum = localDt.setHours(0, 0, 0, 0);
|
|
14
|
-
return localDNum;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Date only. However, the date may still be in UTC.
|
|
18
|
-
* @param dtUtc
|
|
19
|
-
*/
|
|
20
|
-
static dateTimeUtcToLocalDate(dtUtc) {
|
|
21
|
-
const localDt = DateFunc.dateTimeUtcToLocalDateTime(dtUtc);
|
|
22
|
-
const localD = localDt.setHours(0, 0, 0, 0);
|
|
23
|
-
return new Date(localD);
|
|
24
|
-
}
|
|
25
|
-
static localISODateString(dtUtc) {
|
|
26
|
-
const dt = moment(dtUtc).local();
|
|
27
|
-
return dt.format('YYYY-MM-DD');
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* locate date ONLY (no time) to UTC date.
|
|
31
|
-
* @param dt if dt contain time info, it will become dt.setHours(0, 0, 0, 0)
|
|
32
|
-
*/
|
|
33
|
-
static localDateToUtc(d) {
|
|
34
|
-
const dt = moment(d).toDate();
|
|
35
|
-
const n = dt.setHours(0, 0, 0, 0);
|
|
36
|
-
const offset = dt.getTimezoneOffset() * 60000;
|
|
37
|
-
return new Date(n + offset);
|
|
38
|
-
}
|
|
39
|
-
static getTimezoneOffset() {
|
|
40
|
-
const dt = this.today;
|
|
41
|
-
return dt.getTimezoneOffset();
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Transform UTC DateTime to local dateTime.
|
|
45
|
-
* @param dtUtc
|
|
46
|
-
* @param offsetMinutes if not defined, it will be new Date().getTimezoneOffset(). //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
|
|
47
|
-
*/
|
|
48
|
-
static dateTimeUtcToLocalDateTime(dtUtc) {
|
|
49
|
-
const stillUtc = moment.utc(dtUtc).toDate();
|
|
50
|
-
return moment(stillUtc).local().toDate();
|
|
51
|
-
}
|
|
52
|
-
static dateTimeUtcToLocaMoment(dtUtc) {
|
|
53
|
-
const stillUtc = moment.utc(dtUtc);
|
|
54
|
-
return stillUtc.local();
|
|
55
|
-
}
|
|
56
|
-
static getEndOfWeek(dt) {
|
|
57
|
-
return moment(dt).endOf('isoWeek').toDate();
|
|
58
|
-
}
|
|
59
|
-
static getStartOfWeek(dt) {
|
|
60
|
-
return moment(dt).startOf('isoWeek').toDate();
|
|
61
|
-
}
|
|
62
|
-
static getEndOfMonth(dt) {
|
|
63
|
-
// return new Date(dt.getFullYear(), dt.getMonth() + 1, 0, 23, 59, 59, 999);
|
|
64
|
-
return moment(dt).endOf('month').toDate();
|
|
65
|
-
}
|
|
66
|
-
static getStartOfMonth(dt) {
|
|
67
|
-
return moment(dt).startOf('month').toDate();
|
|
68
|
-
}
|
|
69
|
-
static getDaysBetweenDates(dt1, dt2) {
|
|
70
|
-
return this.getDaysBetween(dt1, dt2);
|
|
71
|
-
}
|
|
72
|
-
static getEndOfDate(dt) {
|
|
73
|
-
return dt ? new Date(dt.setHours(23, 59, 59, 999)) :
|
|
74
|
-
new Date(this.now.setHours(23, 59, 59, 999));
|
|
75
|
-
}
|
|
76
|
-
static getStartOfDate(dt) {
|
|
77
|
-
return moment(dt).startOf('day').toDate();
|
|
78
|
-
}
|
|
79
|
-
static getEndOfToday() {
|
|
80
|
-
// return new Date((new Date(Date.now())).setHours(23, 59, 59, 999));
|
|
81
|
-
return moment(Date.now()).endOf('day').toDate();
|
|
82
|
-
}
|
|
83
|
-
static getStartOfToday() {
|
|
84
|
-
// return new Date((new Date(Date.now())).setHours(0, 0, 0, 0));
|
|
85
|
-
return moment(Date.now()).startOf('day').toDate();
|
|
86
|
-
}
|
|
87
|
-
//inspired https://stackoverflow.com/questions/563406/add-days-to-javascript-date
|
|
88
|
-
static addDays(dt, days = 0) {
|
|
89
|
-
const dat = moment(dt);
|
|
90
|
-
dat.add(days, 'days');
|
|
91
|
-
return dat.toDate();
|
|
92
|
-
}
|
|
93
|
-
static subtractDays(dt, days = 0) {
|
|
94
|
-
const dat = moment(dt);
|
|
95
|
-
dat.subtract(days, 'days');
|
|
96
|
-
return dat.toDate();
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Start of today
|
|
100
|
-
*/
|
|
101
|
-
static get today() {
|
|
102
|
-
return this.getStartOfToday();
|
|
103
|
-
}
|
|
104
|
-
static get now() {
|
|
105
|
-
return new Date(Date.now());
|
|
106
|
-
}
|
|
107
|
-
static getNext5MinuteMark() {
|
|
108
|
-
const m = moment().set('second', 0).set('millisecond', 0);
|
|
109
|
-
const minute = m.minute();
|
|
110
|
-
const mod = minute % 5;
|
|
111
|
-
if (mod) {
|
|
112
|
-
const delta = 5 - mod;
|
|
113
|
-
return m.add(delta, 'm').toDate();
|
|
114
|
-
}
|
|
115
|
-
return m.toDate();
|
|
116
|
-
}
|
|
117
|
-
static getYMD(d) {
|
|
118
|
-
return moment(d).format('YYYYMMDD');
|
|
119
|
-
}
|
|
120
|
-
static getDMYWithSlash(d) {
|
|
121
|
-
return moment(d).format('DD/MM/YYYY');
|
|
122
|
-
}
|
|
123
|
-
static getDMYHmWithSlash(d) {
|
|
124
|
-
return moment(d).format('DD/MM/YYYY HH:mm');
|
|
125
|
-
}
|
|
126
|
-
static getMcpTime(dt) {
|
|
127
|
-
return moment(dt).format('HH:mm:ss.SSSZ');
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* In 24 hour format
|
|
131
|
-
* @param dtUtc
|
|
132
|
-
*/
|
|
133
|
-
static getLocalDMYHmWithSlash(dtUtc) {
|
|
134
|
-
const d = DateFunc.dateTimeUtcToLocalDateTime(dtUtc);
|
|
135
|
-
return moment(d).format('DD/MM/YYYY HH:mm');
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Offset minutes comparing with today
|
|
139
|
-
*/
|
|
140
|
-
static getOffsetMinutes(dtUtc) {
|
|
141
|
-
const dm1 = moment(dtUtc);
|
|
142
|
-
const dm2 = moment(new Date().setHours(0, 0, 0, 0));
|
|
143
|
-
return dm1.diff(dm2, 'minutes');
|
|
144
|
-
}
|
|
145
|
-
static getDaysBetween(d1, d2) {
|
|
146
|
-
const dm1 = moment(d1);
|
|
147
|
-
const dm2 = moment(d2);
|
|
148
|
-
return dm2.diff(dm1, 'days');
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Get hour of the date. If Date is not defined, the hour will be current hour.
|
|
152
|
-
* @param dtUtc
|
|
153
|
-
*/
|
|
154
|
-
static getHour(dtUtc) {
|
|
155
|
-
const m = moment(dtUtc);
|
|
156
|
-
return m.hours();
|
|
157
|
-
}
|
|
158
|
-
static getMinute(dtUtc) {
|
|
159
|
-
const m = moment(dtUtc);
|
|
160
|
-
return m.minutes();
|
|
161
|
-
}
|
|
162
|
-
static composeDateTime(dt, h = 0, minute = 0) {
|
|
163
|
-
const mt = moment(dt);
|
|
164
|
-
return new Date(mt.toDate().setHours(h, minute, 0, 0));
|
|
165
|
-
}
|
|
166
|
-
static olderThan24Hours(d) {
|
|
167
|
-
const m = moment(d);
|
|
168
|
-
return moment().diff(m, 'hours') >= 24;
|
|
169
|
-
}
|
|
170
|
-
static olderThan24HoursUtc(dtUtc) {
|
|
171
|
-
return DateFunc.getHourAgeUtc(dtUtc) >= 24;
|
|
172
|
-
}
|
|
173
|
-
static olderThanHours(d, hours) {
|
|
174
|
-
const m = moment(d);
|
|
175
|
-
return moment().diff(m, 'hours') >= hours;
|
|
176
|
-
}
|
|
177
|
-
static olderThanHoursUtc(dtUtc, hours) {
|
|
178
|
-
return DateFunc.getHourAgeUtc(dtUtc) >= hours;
|
|
179
|
-
}
|
|
180
|
-
static olderThanMinutes(d, minutes) {
|
|
181
|
-
const m = moment(d);
|
|
182
|
-
return moment().diff(m, 'minutes') >= minutes;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* It could be 11PM yesterday, and 1 AM today. Actually based on local today.
|
|
186
|
-
*/
|
|
187
|
-
static olderThan1Day(dtUtc) {
|
|
188
|
-
return DateFunc.getDayAgeUtc(dtUtc) > 0;
|
|
189
|
-
}
|
|
190
|
-
static getHourAge(d) {
|
|
191
|
-
const m = moment(d);
|
|
192
|
-
return moment().diff(m, 'hours');
|
|
193
|
-
}
|
|
194
|
-
static getHourAgeUtc(dtUtc) {
|
|
195
|
-
const m = moment.utc(dtUtc);
|
|
196
|
-
return moment.utc().diff(m, 'hours');
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Compare utc date with utc now.
|
|
200
|
-
* @param dtUtc
|
|
201
|
-
*/
|
|
202
|
-
static getDayAgeUtc(dtUtc) {
|
|
203
|
-
const m = moment.utc(dtUtc);
|
|
204
|
-
return moment.utc().diff(m, 'days');
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* How many years from now.
|
|
208
|
-
* @param d
|
|
209
|
-
* @returns
|
|
210
|
-
*/
|
|
211
|
-
static getAge(d) {
|
|
212
|
-
const m = moment(d);
|
|
213
|
-
return moment().diff(m, 'years');
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Year of date.
|
|
217
|
-
* @param d
|
|
218
|
-
* @returns
|
|
219
|
-
*/
|
|
220
|
-
static getYear(d) {
|
|
221
|
-
const m = moment(d);
|
|
222
|
-
return m.year();
|
|
223
|
-
}
|
|
224
|
-
static getUtcNow() {
|
|
225
|
-
return moment.utc().toDate();
|
|
226
|
-
}
|
|
227
|
-
static addMinutes(d, m) {
|
|
228
|
-
return moment(d).add(m, 'm').toDate();
|
|
229
|
-
}
|
|
230
|
-
static addMonth(d, m) {
|
|
231
|
-
return moment(d).add(m, 'M').toDate();
|
|
232
|
-
}
|
|
233
|
-
static getDuration(d1, d2) {
|
|
234
|
-
const md1 = moment(d1);
|
|
235
|
-
const md2 = moment(d2);
|
|
236
|
-
return moment.duration(md2.diff(md1));
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Convert minutes from midnight to HH:mm text
|
|
240
|
-
* @param mins
|
|
241
|
-
*/
|
|
242
|
-
static getHMFromMins(mins) {
|
|
243
|
-
// do not include the first validation check if you want, for example,
|
|
244
|
-
// getTimeFromMins(1530) to equal getTimeFromMins(90) (i.e. mins rollover)
|
|
245
|
-
if (mins >= 24 * 60 || mins < 0) {
|
|
246
|
-
throw new RangeError('Valid input should be greater than or equal to 0 and less than 1440.');
|
|
247
|
-
}
|
|
248
|
-
const h = mins / 60 | 0, m = mins % 60 | 0;
|
|
249
|
-
return moment.utc().hours(h).minutes(m).format('HH:mm');
|
|
250
|
-
}
|
|
251
|
-
static getMinutesSinceMidnight(d) {
|
|
252
|
-
const m = moment(d);
|
|
253
|
-
const midnight = moment(d).startOf('day'); //Mutates the original moment by setting it to the start of a unit of time. So I have better not to use m which wil be changed by calling this function
|
|
254
|
-
return m.diff(midnight, 'minutes');
|
|
255
|
-
}
|
|
256
|
-
static getMinutesBetween(start, end) {
|
|
257
|
-
const m = moment(start);
|
|
258
|
-
const m2 = moment(end);
|
|
259
|
-
return m2.diff(m, 'minutes');
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Parse json string with date serialized into string, and get proper date object back
|
|
263
|
-
* @param s
|
|
264
|
-
*/
|
|
265
|
-
static dateSafeJsonParse(s) {
|
|
266
|
-
return JSON.parse(s, this.dateReviver);
|
|
267
|
-
}
|
|
268
|
-
static dateReviver(key, value) {
|
|
269
|
-
if (DateFunc.isSerializedDate(value)) {
|
|
270
|
-
return (new Date(value));
|
|
271
|
-
}
|
|
272
|
-
// If it's not a date-string, we want to return the value as-is. If we fail to return
|
|
273
|
-
// a value, it will be omitted from the resultant data structure.
|
|
274
|
-
return (value);
|
|
275
|
-
}
|
|
276
|
-
// I determine if the given value is a string that matches the serialized-date pattern.
|
|
277
|
-
static isSerializedDate(value) {
|
|
278
|
-
// Dates are serialized in TZ format, example: '1981-12-20T04:00:14.000Z'.
|
|
279
|
-
const datePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
280
|
-
return (DateFunc.isString(value) && datePattern.test(value));
|
|
281
|
-
}
|
|
282
|
-
// I determine if the given value is a String.
|
|
283
|
-
static isString(value) {
|
|
284
|
-
return ({}.toString.call(value) === '[object String]');
|
|
285
|
-
}
|
|
286
|
-
static dateSafeParse(s) {
|
|
287
|
-
const m = moment(s);
|
|
288
|
-
return m.toDate();
|
|
289
|
-
}
|
|
290
|
-
static composeDateWithMinutes(d, minute) {
|
|
291
|
-
const m = moment(d);
|
|
292
|
-
const midnight = moment(d).startOf('day'); // Mutates the original moment by setting it to the start of a unit of time. So I have better not to use m which wil be changed by calling this function
|
|
293
|
-
midnight.add(minute, 'minutes');
|
|
294
|
-
return midnight.toDate();
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Safe compare since date data may be considered as string rather than date.
|
|
298
|
-
* @param d1
|
|
299
|
-
* @param d2
|
|
300
|
-
*/
|
|
301
|
-
static compare(d1, d2) {
|
|
302
|
-
if (!d1 && !d2) {
|
|
303
|
-
return 0;
|
|
304
|
-
}
|
|
305
|
-
if (!d1) {
|
|
306
|
-
return -NaN;
|
|
307
|
-
}
|
|
308
|
-
if (!d2) {
|
|
309
|
-
return NaN;
|
|
310
|
-
}
|
|
311
|
-
const dd1 = (new Date(d1)).valueOf();
|
|
312
|
-
const dd2 = (new Date(d2)).valueOf();
|
|
313
|
-
return dd1 - dd2;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
1
|
+
import moment from 'moment';
|
|
2
|
+
export class DateFunc {
|
|
3
|
+
/**
|
|
4
|
+
* Transform UTC DateTime to local date without H, M and S. For example, the month day of 2018-01-23T22:00:00Z is 24 in Australia.
|
|
5
|
+
* @param dtUtc
|
|
6
|
+
* @param offsetMinutes if not defined, it will be new Date().getTimezoneOffset(). //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
|
|
7
|
+
*/
|
|
8
|
+
static dateTimeUtcToLocalDateNumber(dtUtc) {
|
|
9
|
+
if (!dtUtc) {
|
|
10
|
+
return 0; //0 is better for calculation by the clients.
|
|
11
|
+
}
|
|
12
|
+
const localDt = DateFunc.dateTimeUtcToLocalDateTime(dtUtc);
|
|
13
|
+
const localDNum = localDt.setHours(0, 0, 0, 0);
|
|
14
|
+
return localDNum;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Date only. However, the date may still be in UTC.
|
|
18
|
+
* @param dtUtc
|
|
19
|
+
*/
|
|
20
|
+
static dateTimeUtcToLocalDate(dtUtc) {
|
|
21
|
+
const localDt = DateFunc.dateTimeUtcToLocalDateTime(dtUtc);
|
|
22
|
+
const localD = localDt.setHours(0, 0, 0, 0);
|
|
23
|
+
return new Date(localD);
|
|
24
|
+
}
|
|
25
|
+
static localISODateString(dtUtc) {
|
|
26
|
+
const dt = moment(dtUtc).local();
|
|
27
|
+
return dt.format('YYYY-MM-DD');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* locate date ONLY (no time) to UTC date.
|
|
31
|
+
* @param dt if dt contain time info, it will become dt.setHours(0, 0, 0, 0)
|
|
32
|
+
*/
|
|
33
|
+
static localDateToUtc(d) {
|
|
34
|
+
const dt = moment(d).toDate();
|
|
35
|
+
const n = dt.setHours(0, 0, 0, 0);
|
|
36
|
+
const offset = dt.getTimezoneOffset() * 60000;
|
|
37
|
+
return new Date(n + offset);
|
|
38
|
+
}
|
|
39
|
+
static getTimezoneOffset() {
|
|
40
|
+
const dt = this.today;
|
|
41
|
+
return dt.getTimezoneOffset();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Transform UTC DateTime to local dateTime.
|
|
45
|
+
* @param dtUtc
|
|
46
|
+
* @param offsetMinutes if not defined, it will be new Date().getTimezoneOffset(). //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
|
|
47
|
+
*/
|
|
48
|
+
static dateTimeUtcToLocalDateTime(dtUtc) {
|
|
49
|
+
const stillUtc = moment.utc(dtUtc).toDate();
|
|
50
|
+
return moment(stillUtc).local().toDate();
|
|
51
|
+
}
|
|
52
|
+
static dateTimeUtcToLocaMoment(dtUtc) {
|
|
53
|
+
const stillUtc = moment.utc(dtUtc);
|
|
54
|
+
return stillUtc.local();
|
|
55
|
+
}
|
|
56
|
+
static getEndOfWeek(dt) {
|
|
57
|
+
return moment(dt).endOf('isoWeek').toDate();
|
|
58
|
+
}
|
|
59
|
+
static getStartOfWeek(dt) {
|
|
60
|
+
return moment(dt).startOf('isoWeek').toDate();
|
|
61
|
+
}
|
|
62
|
+
static getEndOfMonth(dt) {
|
|
63
|
+
// return new Date(dt.getFullYear(), dt.getMonth() + 1, 0, 23, 59, 59, 999);
|
|
64
|
+
return moment(dt).endOf('month').toDate();
|
|
65
|
+
}
|
|
66
|
+
static getStartOfMonth(dt) {
|
|
67
|
+
return moment(dt).startOf('month').toDate();
|
|
68
|
+
}
|
|
69
|
+
static getDaysBetweenDates(dt1, dt2) {
|
|
70
|
+
return this.getDaysBetween(dt1, dt2);
|
|
71
|
+
}
|
|
72
|
+
static getEndOfDate(dt) {
|
|
73
|
+
return dt ? new Date(dt.setHours(23, 59, 59, 999)) :
|
|
74
|
+
new Date(this.now.setHours(23, 59, 59, 999));
|
|
75
|
+
}
|
|
76
|
+
static getStartOfDate(dt) {
|
|
77
|
+
return moment(dt).startOf('day').toDate();
|
|
78
|
+
}
|
|
79
|
+
static getEndOfToday() {
|
|
80
|
+
// return new Date((new Date(Date.now())).setHours(23, 59, 59, 999));
|
|
81
|
+
return moment(Date.now()).endOf('day').toDate();
|
|
82
|
+
}
|
|
83
|
+
static getStartOfToday() {
|
|
84
|
+
// return new Date((new Date(Date.now())).setHours(0, 0, 0, 0));
|
|
85
|
+
return moment(Date.now()).startOf('day').toDate();
|
|
86
|
+
}
|
|
87
|
+
//inspired https://stackoverflow.com/questions/563406/add-days-to-javascript-date
|
|
88
|
+
static addDays(dt, days = 0) {
|
|
89
|
+
const dat = moment(dt);
|
|
90
|
+
dat.add(days, 'days');
|
|
91
|
+
return dat.toDate();
|
|
92
|
+
}
|
|
93
|
+
static subtractDays(dt, days = 0) {
|
|
94
|
+
const dat = moment(dt);
|
|
95
|
+
dat.subtract(days, 'days');
|
|
96
|
+
return dat.toDate();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Start of today
|
|
100
|
+
*/
|
|
101
|
+
static get today() {
|
|
102
|
+
return this.getStartOfToday();
|
|
103
|
+
}
|
|
104
|
+
static get now() {
|
|
105
|
+
return new Date(Date.now());
|
|
106
|
+
}
|
|
107
|
+
static getNext5MinuteMark() {
|
|
108
|
+
const m = moment().set('second', 0).set('millisecond', 0);
|
|
109
|
+
const minute = m.minute();
|
|
110
|
+
const mod = minute % 5;
|
|
111
|
+
if (mod) {
|
|
112
|
+
const delta = 5 - mod;
|
|
113
|
+
return m.add(delta, 'm').toDate();
|
|
114
|
+
}
|
|
115
|
+
return m.toDate();
|
|
116
|
+
}
|
|
117
|
+
static getYMD(d) {
|
|
118
|
+
return moment(d).format('YYYYMMDD');
|
|
119
|
+
}
|
|
120
|
+
static getDMYWithSlash(d) {
|
|
121
|
+
return moment(d).format('DD/MM/YYYY');
|
|
122
|
+
}
|
|
123
|
+
static getDMYHmWithSlash(d) {
|
|
124
|
+
return moment(d).format('DD/MM/YYYY HH:mm');
|
|
125
|
+
}
|
|
126
|
+
static getMcpTime(dt) {
|
|
127
|
+
return moment(dt).format('HH:mm:ss.SSSZ');
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* In 24 hour format
|
|
131
|
+
* @param dtUtc
|
|
132
|
+
*/
|
|
133
|
+
static getLocalDMYHmWithSlash(dtUtc) {
|
|
134
|
+
const d = DateFunc.dateTimeUtcToLocalDateTime(dtUtc);
|
|
135
|
+
return moment(d).format('DD/MM/YYYY HH:mm');
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Offset minutes comparing with today
|
|
139
|
+
*/
|
|
140
|
+
static getOffsetMinutes(dtUtc) {
|
|
141
|
+
const dm1 = moment(dtUtc);
|
|
142
|
+
const dm2 = moment(new Date().setHours(0, 0, 0, 0));
|
|
143
|
+
return dm1.diff(dm2, 'minutes');
|
|
144
|
+
}
|
|
145
|
+
static getDaysBetween(d1, d2) {
|
|
146
|
+
const dm1 = moment(d1);
|
|
147
|
+
const dm2 = moment(d2);
|
|
148
|
+
return dm2.diff(dm1, 'days');
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get hour of the date. If Date is not defined, the hour will be current hour.
|
|
152
|
+
* @param dtUtc
|
|
153
|
+
*/
|
|
154
|
+
static getHour(dtUtc) {
|
|
155
|
+
const m = moment(dtUtc);
|
|
156
|
+
return m.hours();
|
|
157
|
+
}
|
|
158
|
+
static getMinute(dtUtc) {
|
|
159
|
+
const m = moment(dtUtc);
|
|
160
|
+
return m.minutes();
|
|
161
|
+
}
|
|
162
|
+
static composeDateTime(dt, h = 0, minute = 0) {
|
|
163
|
+
const mt = moment(dt);
|
|
164
|
+
return new Date(mt.toDate().setHours(h, minute, 0, 0));
|
|
165
|
+
}
|
|
166
|
+
static olderThan24Hours(d) {
|
|
167
|
+
const m = moment(d);
|
|
168
|
+
return moment().diff(m, 'hours') >= 24;
|
|
169
|
+
}
|
|
170
|
+
static olderThan24HoursUtc(dtUtc) {
|
|
171
|
+
return DateFunc.getHourAgeUtc(dtUtc) >= 24;
|
|
172
|
+
}
|
|
173
|
+
static olderThanHours(d, hours) {
|
|
174
|
+
const m = moment(d);
|
|
175
|
+
return moment().diff(m, 'hours') >= hours;
|
|
176
|
+
}
|
|
177
|
+
static olderThanHoursUtc(dtUtc, hours) {
|
|
178
|
+
return DateFunc.getHourAgeUtc(dtUtc) >= hours;
|
|
179
|
+
}
|
|
180
|
+
static olderThanMinutes(d, minutes) {
|
|
181
|
+
const m = moment(d);
|
|
182
|
+
return moment().diff(m, 'minutes') >= minutes;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* It could be 11PM yesterday, and 1 AM today. Actually based on local today.
|
|
186
|
+
*/
|
|
187
|
+
static olderThan1Day(dtUtc) {
|
|
188
|
+
return DateFunc.getDayAgeUtc(dtUtc) > 0;
|
|
189
|
+
}
|
|
190
|
+
static getHourAge(d) {
|
|
191
|
+
const m = moment(d);
|
|
192
|
+
return moment().diff(m, 'hours');
|
|
193
|
+
}
|
|
194
|
+
static getHourAgeUtc(dtUtc) {
|
|
195
|
+
const m = moment.utc(dtUtc);
|
|
196
|
+
return moment.utc().diff(m, 'hours');
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Compare utc date with utc now.
|
|
200
|
+
* @param dtUtc
|
|
201
|
+
*/
|
|
202
|
+
static getDayAgeUtc(dtUtc) {
|
|
203
|
+
const m = moment.utc(dtUtc);
|
|
204
|
+
return moment.utc().diff(m, 'days');
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* How many years from now.
|
|
208
|
+
* @param d
|
|
209
|
+
* @returns
|
|
210
|
+
*/
|
|
211
|
+
static getAge(d) {
|
|
212
|
+
const m = moment(d);
|
|
213
|
+
return moment().diff(m, 'years');
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Year of date.
|
|
217
|
+
* @param d
|
|
218
|
+
* @returns
|
|
219
|
+
*/
|
|
220
|
+
static getYear(d) {
|
|
221
|
+
const m = moment(d);
|
|
222
|
+
return m.year();
|
|
223
|
+
}
|
|
224
|
+
static getUtcNow() {
|
|
225
|
+
return moment.utc().toDate();
|
|
226
|
+
}
|
|
227
|
+
static addMinutes(d, m) {
|
|
228
|
+
return moment(d).add(m, 'm').toDate();
|
|
229
|
+
}
|
|
230
|
+
static addMonth(d, m) {
|
|
231
|
+
return moment(d).add(m, 'M').toDate();
|
|
232
|
+
}
|
|
233
|
+
static getDuration(d1, d2) {
|
|
234
|
+
const md1 = moment(d1);
|
|
235
|
+
const md2 = moment(d2);
|
|
236
|
+
return moment.duration(md2.diff(md1));
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Convert minutes from midnight to HH:mm text
|
|
240
|
+
* @param mins
|
|
241
|
+
*/
|
|
242
|
+
static getHMFromMins(mins) {
|
|
243
|
+
// do not include the first validation check if you want, for example,
|
|
244
|
+
// getTimeFromMins(1530) to equal getTimeFromMins(90) (i.e. mins rollover)
|
|
245
|
+
if (mins >= 24 * 60 || mins < 0) {
|
|
246
|
+
throw new RangeError('Valid input should be greater than or equal to 0 and less than 1440.');
|
|
247
|
+
}
|
|
248
|
+
const h = mins / 60 | 0, m = mins % 60 | 0;
|
|
249
|
+
return moment.utc().hours(h).minutes(m).format('HH:mm');
|
|
250
|
+
}
|
|
251
|
+
static getMinutesSinceMidnight(d) {
|
|
252
|
+
const m = moment(d);
|
|
253
|
+
const midnight = moment(d).startOf('day'); //Mutates the original moment by setting it to the start of a unit of time. So I have better not to use m which wil be changed by calling this function
|
|
254
|
+
return m.diff(midnight, 'minutes');
|
|
255
|
+
}
|
|
256
|
+
static getMinutesBetween(start, end) {
|
|
257
|
+
const m = moment(start);
|
|
258
|
+
const m2 = moment(end);
|
|
259
|
+
return m2.diff(m, 'minutes');
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Parse json string with date serialized into string, and get proper date object back
|
|
263
|
+
* @param s
|
|
264
|
+
*/
|
|
265
|
+
static dateSafeJsonParse(s) {
|
|
266
|
+
return JSON.parse(s, this.dateReviver);
|
|
267
|
+
}
|
|
268
|
+
static dateReviver(key, value) {
|
|
269
|
+
if (DateFunc.isSerializedDate(value)) {
|
|
270
|
+
return (new Date(value));
|
|
271
|
+
}
|
|
272
|
+
// If it's not a date-string, we want to return the value as-is. If we fail to return
|
|
273
|
+
// a value, it will be omitted from the resultant data structure.
|
|
274
|
+
return (value);
|
|
275
|
+
}
|
|
276
|
+
// I determine if the given value is a string that matches the serialized-date pattern.
|
|
277
|
+
static isSerializedDate(value) {
|
|
278
|
+
// Dates are serialized in TZ format, example: '1981-12-20T04:00:14.000Z'.
|
|
279
|
+
const datePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
280
|
+
return (DateFunc.isString(value) && datePattern.test(value));
|
|
281
|
+
}
|
|
282
|
+
// I determine if the given value is a String.
|
|
283
|
+
static isString(value) {
|
|
284
|
+
return ({}.toString.call(value) === '[object String]');
|
|
285
|
+
}
|
|
286
|
+
static dateSafeParse(s) {
|
|
287
|
+
const m = moment(s);
|
|
288
|
+
return m.toDate();
|
|
289
|
+
}
|
|
290
|
+
static composeDateWithMinutes(d, minute) {
|
|
291
|
+
const m = moment(d);
|
|
292
|
+
const midnight = moment(d).startOf('day'); // Mutates the original moment by setting it to the start of a unit of time. So I have better not to use m which wil be changed by calling this function
|
|
293
|
+
midnight.add(minute, 'minutes');
|
|
294
|
+
return midnight.toDate();
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Safe compare since date data may be considered as string rather than date.
|
|
298
|
+
* @param d1
|
|
299
|
+
* @param d2
|
|
300
|
+
*/
|
|
301
|
+
static compare(d1, d2) {
|
|
302
|
+
if (!d1 && !d2) {
|
|
303
|
+
return 0;
|
|
304
|
+
}
|
|
305
|
+
if (!d1) {
|
|
306
|
+
return -NaN;
|
|
307
|
+
}
|
|
308
|
+
if (!d2) {
|
|
309
|
+
return NaN;
|
|
310
|
+
}
|
|
311
|
+
const dd1 = (new Date(d1)).valueOf();
|
|
312
|
+
const dd2 = (new Date(d2)).valueOf();
|
|
313
|
+
return dd1 - dd2;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
316
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZUZ1bmMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9ubWNlLWZ1bmMvc3JjL19mdW5jL2RhdGVGdW5jLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUU1QixNQUFNLE9BQU8sUUFBUTtJQUVwQjs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLDRCQUE0QixDQUFDLEtBQThCO1FBQ2pFLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDWCxPQUFPLENBQUMsQ0FBQyxDQUFDLDZDQUE2QztTQUN2RDtRQUVELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQywwQkFBMEIsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMzRCxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRS9DLE9BQU8sU0FBUyxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsc0JBQXNCLENBQUMsS0FBOEI7UUFDM0QsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLDBCQUEwQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDNUMsT0FBTyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN6QixDQUFDO0lBRUQsTUFBTSxDQUFDLGtCQUFrQixDQUFDLEtBQThCO1FBQ3ZELE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNqQyxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxjQUFj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O1xyXG5cclxuZXhwb3J0IGNsYXNzIERhdGVGdW5jIHtcclxuXHJcblx0LyoqXHJcblx0ICogVHJhbnNmb3JtIFVUQyBEYXRlVGltZSB0byBsb2NhbCBkYXRlIHdpdGhvdXQgSCwgTSBhbmQgUy4gRm9yIGV4YW1wbGUsIHRoZSBtb250aCBkYXkgb2YgMjAxOC0wMS0yM1QyMjowMDowMFogaXMgMjQgaW4gQXVzdHJhbGlhLlxyXG5cdCAqIEBwYXJhbSBkdFV0Y1xyXG5cdCAqIEBwYXJhbSBvZmZzZXRNaW51dGVzIGlmIG5vdCBkZWZpbmVkLCBpdCB3aWxsIGJlIG5ldyBEYXRlKCkuZ2V0VGltZXpvbmVPZmZzZXQoKS4gLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9EYXRlL2dldFRpbWV6b25lT2Zmc2V0XHJcblx0ICovXHJcblx0c3RhdGljIGRhdGVUaW1lVXRjVG9Mb2NhbERhdGVOdW1iZXIoZHRVdGM6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcclxuXHRcdGlmICghZHRVdGMpIHtcclxuXHRcdFx0cmV0dXJuIDA7IC8vMCBpcyBiZXR0ZXIgZm9yIGNhbGN1bGF0aW9uIGJ5IHRoZSBjbGllbnRzLlxyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGxvY2FsRHQgPSBEYXRlRnVuYy5kYXRlVGltZVV0Y1RvTG9jYWxEYXRlVGltZShkdFV0Yyk7XHJcblx0XHRjb25zdCBsb2NhbEROdW0gPSBsb2NhbER0LnNldEhvdXJzKDAsIDAsIDAsIDApO1xyXG5cclxuXHRcdHJldHVybiBsb2NhbEROdW07XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBEYXRlIG9ubHkuIEhvd2V2ZXIsIHRoZSBkYXRlIG1heSBzdGlsbCBiZSBpbiBVVEMuXHJcblx0ICogQHBhcmFtIGR0VXRjXHJcblx0ICovXHJcblx0c3RhdGljIGRhdGVUaW1lVXRjVG9Mb2NhbERhdGUoZHRVdGM6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkKTogRGF0ZSB7XHJcblx0XHRjb25zdCBsb2NhbER0ID0gRGF0ZUZ1bmMuZGF0ZVRpbWVVdGNUb0xvY2FsRGF0ZVRpbWUoZHRVdGMpO1xyXG5cdFx0Y29uc3QgbG9jYWxEID0gbG9jYWxEdC5zZXRIb3VycygwLCAwLCAwLCAwKTtcclxuXHRcdHJldHVybiBuZXcgRGF0ZShsb2NhbEQpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGxvY2FsSVNPRGF0ZVN0cmluZyhkdFV0YzogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xyXG5cdFx0Y29uc3QgZHQgPSBtb21lbnQoZHRVdGMpLmxvY2FsKCk7XHJcblx0XHRyZXR1cm4gZHQuZm9ybWF0KCdZWVlZLU1NLUREJyk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBsb2NhdGUgZGF0ZSBPTkxZIChubyB0aW1lKSB0byBVVEMgZGF0ZS5cclxuXHQgKiBAcGFyYW0gZHQgaWYgZHQgY29udGFpbiB0aW1lIGluZm8sIGl0IHdpbGwgYmVjb21lIGR0LnNldEhvdXJzKDAsIDAsIDAsIDApXHJcblx0ICovXHJcblx0c3RhdGljIGxvY2FsRGF0ZVRvVXRjKGQ6IERhdGUgfCBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkIHwgc3RyaW5nKTogRGF0ZSB7XHJcblx0XHRjb25zdCBkdCA9IG1vbWVudChkKS50b0RhdGUoKTtcclxuXHRcdGNvbnN0IG4gPSBkdC5zZXRIb3VycygwLCAwLCAwLCAwKTtcclxuXHRcdGNvbnN0IG9mZnNldCA9IGR0LmdldFRpbWV6b25lT2Zmc2V0KCkgKiA2MDAwMDtcclxuXHRcdHJldHVybiBuZXcgRGF0ZShuICsgb2Zmc2V0KTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRUaW1lem9uZU9mZnNldCgpOiBudW1iZXIge1xyXG5cdFx0Y29uc3QgZHQgPSB0aGlzLnRvZGF5O1xyXG5cdFx0cmV0dXJuIGR0LmdldFRpbWV6b25lT2Zmc2V0KCk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBUcmFuc2Zvcm0gVVRDIERhdGVUaW1lIHRvIGxvY2FsIGRhdGVUaW1lLlxyXG5cdCAqIEBwYXJhbSBkdFV0Y1xyXG5cdCAqIEBwYXJhbSBvZmZzZXRNaW51dGVzIGlmIG5vdCBkZWZpbmVkLCBpdCB3aWxsIGJlIG5ldyBEYXRlKCkuZ2V0VGltZXpvbmVPZmZzZXQoKS4gLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9EYXRlL2dldFRpbWV6b25lT2Zmc2V0XHJcblx0ICovXHJcblx0c3RhdGljIGRhdGVUaW1lVXRjVG9Mb2NhbERhdGVUaW1lKGR0VXRjOiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCk6IERhdGUge1xyXG5cdFx0Y29uc3Qgc3RpbGxVdGMgPSBtb21lbnQudXRjKGR0VXRjKS50b0RhdGUoKTtcclxuXHRcdHJldHVybiBtb21lbnQoc3RpbGxVdGMpLmxvY2FsKCkudG9EYXRlKCk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZGF0ZVRpbWVVdGNUb0xvY2FNb21lbnQoZHRVdGM6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkKTogbW9tZW50Lk1vbWVudCB7XHJcblx0XHRjb25zdCBzdGlsbFV0YyA9IG1vbWVudC51dGMoZHRVdGMpO1xyXG5cdFx0cmV0dXJuIHN0aWxsVXRjLmxvY2FsKCk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZ2V0RW5kT2ZXZWVrKGR0OiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCB8IG51bWJlcikge1xyXG5cdFx0cmV0dXJuIG1vbWVudChkdCkuZW5kT2YoJ2lzb1dlZWsnKS50b0RhdGUoKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRTdGFydE9mV2VlayhkdDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQgfCBudW1iZXIpIHtcclxuXHRcdHJldHVybiBtb21lbnQoZHQpLnN0YXJ0T2YoJ2lzb1dlZWsnKS50b0RhdGUoKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRFbmRPZk1vbnRoKGR0OiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCB8IG51bWJlcikge1xyXG5cdFx0Ly8gIHJldHVybiBuZXcgRGF0ZShkdC5nZXRGdWxsWWVhcigpLCBkdC5nZXRNb250aCgpICsgMSwgMCwgMjMsIDU5LCA1OSwgOTk5KTtcclxuXHRcdHJldHVybiBtb21lbnQoZHQpLmVuZE9mKCdtb250aCcpLnRvRGF0ZSgpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGdldFN0YXJ0T2ZNb250aChkdDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQgfCBudW1iZXIpIHtcclxuXHRcdHJldHVybiBtb21lbnQoZHQpLnN0YXJ0T2YoJ21vbnRoJykudG9EYXRlKCk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZ2V0RGF5c0JldHdlZW5EYXRlcyhkdDE6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkLCBkdDI6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5nZXREYXlzQmV0d2VlbihkdDEsIGR0Mik7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZ2V0RW5kT2ZEYXRlKGR0OiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCk6IERhdGUge1xyXG5cdFx0cmV0dXJuIGR0ID8gbmV3IERhdGUoZHQuc2V0SG91cnMoMjMsIDU5LCA1OSwgOTk5KSkgOlxyXG5cdFx0XHRuZXcgRGF0ZSh0aGlzLm5vdy5zZXRIb3VycygyMywgNTksIDU5LCA5OTkpKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRTdGFydE9mRGF0ZShkdDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpOiBEYXRlIHtcclxuXHRcdHJldHVybiBtb21lbnQoZHQpLnN0YXJ0T2YoJ2RheScpLnRvRGF0ZSgpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGdldEVuZE9mVG9kYXkoKTogRGF0ZSB7XHJcblx0XHQvL1x0cmV0dXJuIG5ldyBEYXRlKChuZXcgRGF0ZShEYXRlLm5vdygpKSkuc2V0SG91cnMoMjMsIDU5LCA1OSwgOTk5KSk7XHJcblx0XHRyZXR1cm4gbW9tZW50KERhdGUubm93KCkpLmVuZE9mKCdkYXknKS50b0RhdGUoKTtcclxuXHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZ2V0U3RhcnRPZlRvZGF5KCk6IERhdGUge1xyXG5cdFx0Ly9cdHJldHVybiBuZXcgRGF0ZSgobmV3IERhdGUoRGF0ZS5ub3coKSkpLnNldEhvdXJzKDAsIDAsIDAsIDApKTtcclxuXHRcdHJldHVybiBtb21lbnQoRGF0ZS5ub3coKSkuc3RhcnRPZignZGF5JykudG9EYXRlKCk7XHJcblx0fVxyXG5cclxuXHQvL2luc3BpcmVkIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzU2MzQwNi9hZGQtZGF5cy10by1qYXZhc2NyaXB0LWRhdGVcclxuXHRzdGF0aWMgYWRkRGF5cyhkdDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQsIGRheXM6IG51bWJlciA9IDApIHtcclxuXHRcdGNvbnN0IGRhdCA9IG1vbWVudChkdCk7XHJcblx0XHRkYXQuYWRkKGRheXMsICdkYXlzJyk7XHJcblx0XHRyZXR1cm4gZGF0LnRvRGF0ZSgpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIHN1YnRyYWN0RGF5cyhkdDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQsIGRheXM6IG51bWJlciA9IDApIHtcclxuXHRcdGNvbnN0IGRhdCA9IG1vbWVudChkdCk7XHJcblx0XHRkYXQuc3VidHJhY3QoZGF5cywgJ2RheXMnKTtcclxuXHRcdHJldHVybiBkYXQudG9EYXRlKCk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBTdGFydCBvZiB0b2RheVxyXG5cdCAqL1xyXG5cdHN0YXRpYyBnZXQgdG9kYXkoKTogRGF0ZSB7XHJcblx0XHRyZXR1cm4gdGhpcy5nZXRTdGFydE9mVG9kYXkoKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXQgbm93KCk6IERhdGUge1xyXG5cdFx0cmV0dXJuIG5ldyBEYXRlKERhdGUubm93KCkpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGdldE5leHQ1TWludXRlTWFyaygpOiBEYXRlIHtcclxuXHRcdGNvbnN0IG0gPSBtb21lbnQoKS5zZXQoJ3NlY29uZCcsIDApLnNldCgnbWlsbGlzZWNvbmQnLCAwKTtcclxuXHRcdGNvbnN0IG1pbnV0ZSA9IG0ubWludXRlKCk7XHJcblx0XHRjb25zdCBtb2QgPSBtaW51dGUgJSA1O1xyXG5cdFx0aWYgKG1vZCkge1xyXG5cdFx0XHRjb25zdCBkZWx0YSA9IDUgLSBtb2Q7XHJcblx0XHRcdHJldHVybiBtLmFkZChkZWx0YSwgJ20nKS50b0RhdGUoKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gbS50b0RhdGUoKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRZTUQoZDogRGF0ZSkge1xyXG5cdFx0cmV0dXJuIG1vbWVudChkKS5mb3JtYXQoJ1lZWVlNTUREJyk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZ2V0RE1ZV2l0aFNsYXNoKGQ6IERhdGUpIHtcclxuXHRcdHJldHVybiBtb21lbnQoZCkuZm9ybWF0KCdERC9NTS9ZWVlZJyk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZ2V0RE1ZSG1XaXRoU2xhc2goZDogRGF0ZSkge1xyXG5cdFx0cmV0dXJuIG1vbWVudChkKS5mb3JtYXQoJ0REL01NL1lZWVkgSEg6bW0nKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRNY3BUaW1lKGR0OiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCkge1xyXG5cdFx0cmV0dXJuIG1vbWVudChkdCkuZm9ybWF0KCdISDptbTpzcy5TU1NaJyk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBJbiAyNCBob3VyIGZvcm1hdFxyXG5cdCAqIEBwYXJhbSBkdFV0Y1xyXG5cdCAqL1xyXG5cdHN0YXRpYyBnZXRMb2NhbERNWUhtV2l0aFNsYXNoKGR0VXRjOiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCkge1xyXG5cdFx0Y29uc3QgZCA9IERhdGVGdW5jLmRhdGVUaW1lVXRjVG9Mb2NhbERhdGVUaW1lKGR0VXRjKTtcclxuXHRcdHJldHVybiBtb21lbnQoZCkuZm9ybWF0KCdERC9NTS9ZWVlZIEhIOm1tJyk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBPZmZzZXQgbWludXRlcyBjb21wYXJpbmcgd2l0aCB0b2RheVxyXG5cdCAqL1xyXG5cdHN0YXRpYyBnZXRPZmZzZXRNaW51dGVzKGR0VXRjOiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCB8IG51bWJlcik6IG51bWJlciB7XHJcblx0XHRjb25zdCBkbTEgPSBtb21lbnQoZHRVdGMpO1xyXG5cdFx0Y29uc3QgZG0yID0gbW9tZW50KG5ldyBEYXRlKCkuc2V0SG91cnMoMCwgMCwgMCwgMCkpO1xyXG5cdFx0cmV0dXJuIGRtMS5kaWZmKGRtMiwgJ21pbnV0ZXMnKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXREYXlzQmV0d2VlbihkMT86IERhdGUgfCBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkLCBkMj86IERhdGUgfCBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcclxuXHRcdGNvbnN0IGRtMSA9IG1vbWVudChkMSk7XHJcblx0XHRjb25zdCBkbTIgPSBtb21lbnQoZDIpO1xyXG5cdFx0cmV0dXJuIGRtMi5kaWZmKGRtMSwgJ2RheXMnKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEdldCBob3VyIG9mIHRoZSBkYXRlLiBJZiBEYXRlIGlzIG5vdCBkZWZpbmVkLCB0aGUgaG91ciB3aWxsIGJlIGN1cnJlbnQgaG91ci5cclxuXHQgKiBAcGFyYW0gZHRVdGNcclxuXHQgKi9cclxuXHRzdGF0aWMgZ2V0SG91cihkdFV0YzogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQgfCBudW1iZXIpOiBudW1iZXIge1xyXG5cdFx0Y29uc3QgbSA9IG1vbWVudChkdFV0Yyk7XHJcblx0XHRyZXR1cm4gbS5ob3VycygpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGdldE1pbnV0ZShkdFV0YzogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQgfCBudW1iZXIpOiBudW1iZXIge1xyXG5cdFx0Y29uc3QgbSA9IG1vbWVudChkdFV0Yyk7XHJcblx0XHRyZXR1cm4gbS5taW51dGVzKCk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgY29tcG9zZURhdGVUaW1lKGR0OiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCwgaDogbnVtYmVyID0gMCwgbWludXRlOiBudW1iZXIgPSAwKTogRGF0ZSB7XHJcblx0XHRjb25zdCBtdCA9IG1vbWVudChkdCk7XHJcblx0XHRyZXR1cm4gbmV3IERhdGUobXQudG9EYXRlKCkuc2V0SG91cnMoaCwgbWludXRlLCAwLCAwKSk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgb2xkZXJUaGFuMjRIb3VycyhkOiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xyXG5cdFx0Y29uc3QgbSA9IG1vbWVudChkKTtcclxuXHRcdHJldHVybiBtb21lbnQoKS5kaWZmKG0sICdob3VycycpID49IDI0O1xyXG5cdH1cclxuXHJcblx0c3RhdGljIG9sZGVyVGhhbjI0SG91cnNVdGMoZHRVdGM6IERhdGUgfCBudWxsIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XHJcblx0XHRyZXR1cm4gRGF0ZUZ1bmMuZ2V0SG91ckFnZVV0YyhkdFV0YykgPj0gMjQ7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgb2xkZXJUaGFuSG91cnMoZDogRGF0ZSwgaG91cnM6IG51bWJlcikge1xyXG5cdFx0Y29uc3QgbSA9IG1vbWVudChkKTtcclxuXHRcdHJldHVybiBtb21lbnQoKS5kaWZmKG0sICdob3VycycpID49IGhvdXJzO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIG9sZGVyVGhhbkhvdXJzVXRjKGR0VXRjOiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCwgaG91cnM6IG51bWJlcik6IGJvb2xlYW4ge1xyXG5cdFx0cmV0dXJuIERhdGVGdW5jLmdldEhvdXJBZ2VVdGMoZHRVdGMpID49IGhvdXJzO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIG9sZGVyVGhhbk1pbnV0ZXMoZDogRGF0ZSwgbWludXRlczogbnVtYmVyKSB7XHJcblx0XHRjb25zdCBtID0gbW9tZW50KGQpO1xyXG5cdFx0cmV0dXJuIG1vbWVudCgpLmRpZmYobSwgJ21pbnV0ZXMnKSA+PSBtaW51dGVzO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogSXQgY291bGQgYmUgMTFQTSB5ZXN0ZXJkYXksIGFuZCAxIEFNIHRvZGF5LiBBY3R1YWxseSBiYXNlZCBvbiBsb2NhbCB0b2RheS5cclxuXHQgKi9cclxuXHRzdGF0aWMgb2xkZXJUaGFuMURheShkdFV0YzogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcclxuXHRcdHJldHVybiBEYXRlRnVuYy5nZXREYXlBZ2VVdGMoZHRVdGMpID4gMDtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRIb3VyQWdlKGQ6IERhdGUpIHtcclxuXHRcdGNvbnN0IG0gPSBtb21lbnQoZCk7XHJcblx0XHRyZXR1cm4gbW9tZW50KCkuZGlmZihtLCAnaG91cnMnKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRIb3VyQWdlVXRjKGR0VXRjOiBEYXRlIHwgbnVsbCB8IHVuZGVmaW5lZCkge1xyXG5cdFx0Y29uc3QgbSA9IG1vbWVudC51dGMoZHRVdGMpO1xyXG5cdFx0cmV0dXJuIG1vbWVudC51dGMoKS5kaWZmKG0sICdob3VycycpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogQ29tcGFyZSB1dGMgZGF0ZSB3aXRoIHV0YyBub3cuXHJcblx0ICogQHBhcmFtIGR0VXRjXHJcblx0ICovXHJcblx0c3RhdGljIGdldERheUFnZVV0YyhkdFV0YzogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpIHtcclxuXHRcdGNvbnN0IG0gPSBtb21lbnQudXRjKGR0VXRjKTtcclxuXHRcdHJldHVybiBtb21lbnQudXRjKCkuZGlmZihtLCAnZGF5cycpO1xyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogSG93IG1hbnkgeWVhcnMgZnJvbSBub3cuXHJcblx0ICogQHBhcmFtIGQgXHJcblx0ICogQHJldHVybnMgXHJcblx0ICovXHJcblx0c3RhdGljIGdldEFnZShkOiBEYXRlKSB7XHJcblx0XHRjb25zdCBtID0gbW9tZW50KGQpO1xyXG5cdFx0cmV0dXJuIG1vbWVudCgpLmRpZmYobSwgJ3llYXJzJyk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBZZWFyIG9mIGRhdGUuXHJcblx0ICogQHBhcmFtIGQgXHJcblx0ICogQHJldHVybnMgXHJcblx0ICovXHJcblx0c3RhdGljIGdldFllYXIoZDogRGF0ZSkge1xyXG5cdFx0Y29uc3QgbSA9IG1vbWVudChkKTtcclxuXHRcdHJldHVybiBtLnllYXIoKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRVdGNOb3coKTogRGF0ZSB7XHJcblx0XHRyZXR1cm4gbW9tZW50LnV0YygpLnRvRGF0ZSgpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGFkZE1pbnV0ZXMoZDogRGF0ZSwgbTogbnVtYmVyKTogRGF0ZSB7XHJcblx0XHRyZXR1cm4gbW9tZW50KGQpLmFkZChtLCAnbScpLnRvRGF0ZSgpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGFkZE1vbnRoKGQ6IERhdGUsIG06IG51bWJlcik6IERhdGUge1xyXG5cdFx0cmV0dXJuIG1vbWVudChkKS5hZGQobSwgJ00nKS50b0RhdGUoKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXREdXJhdGlvbihkMTogRGF0ZSwgZDI6IERhdGUpIHtcclxuXHRcdGNvbnN0IG1kMSA9IG1vbWVudChkMSk7XHJcblx0XHRjb25zdCBtZDIgPSBtb21lbnQoZDIpO1xyXG5cdFx0cmV0dXJuIG1vbWVudC5kdXJhdGlvbihtZDIuZGlmZihtZDEpKTtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIENvbnZlcnQgbWludXRlcyBmcm9tIG1pZG5pZ2h0IHRvIEhIOm1tIHRleHRcclxuXHQgKiBAcGFyYW0gbWluc1xyXG5cdCAqL1xyXG5cdHN0YXRpYyBnZXRITUZyb21NaW5zKG1pbnM6IG51bWJlcik6IHN0cmluZyB7XHJcblx0XHQvLyBkbyBub3QgaW5jbHVkZSB0aGUgZmlyc3QgdmFsaWRhdGlvbiBjaGVjayBpZiB5b3Ugd2FudCwgZm9yIGV4YW1wbGUsXHJcblx0XHQvLyBnZXRUaW1lRnJvbU1pbnMoMTUzMCkgdG8gZXF1YWwgZ2V0VGltZUZyb21NaW5zKDkwKSAoaS5lLiBtaW5zIHJvbGxvdmVyKVxyXG5cdFx0aWYgKG1pbnMgPj0gMjQgKiA2MCB8fCBtaW5zIDwgMCkge1xyXG5cdFx0XHR0aHJvdyBuZXcgUmFuZ2VFcnJvcignVmFsaWQgaW5wdXQgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAwIGFuZCBsZXNzIHRoYW4gMTQ0MC4nKTtcclxuXHRcdH1cclxuXHRcdGNvbnN0IGggPSBtaW5zIC8gNjAgfCAwLFxyXG5cdFx0XHRtID0gbWlucyAlIDYwIHwgMDtcclxuXHRcdHJldHVybiBtb21lbnQudXRjKCkuaG91cnMoaCkubWludXRlcyhtKS5mb3JtYXQoJ0hIOm1tJyk7XHJcblx0fVxyXG5cclxuXHRzdGF0aWMgZ2V0TWludXRlc1NpbmNlTWlkbmlnaHQoZDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpIHtcclxuXHRcdGNvbnN0IG0gPSBtb21lbnQoZCk7XHJcblx0XHRjb25zdCBtaWRuaWdodCA9IG1vbWVudChkKS5zdGFydE9mKCdkYXknKTsgLy9NdXRhdGVzIHRoZSBvcmlnaW5hbCBtb21lbnQgYnkgc2V0dGluZyBpdCB0byB0aGUgc3RhcnQgb2YgYSB1bml0IG9mIHRpbWUuIFNvIEkgaGF2ZSBiZXR0ZXIgbm90IHRvIHVzZSBtIHdoaWNoIHdpbCBiZSBjaGFuZ2VkIGJ5IGNhbGxpbmcgdGhpcyBmdW5jdGlvblxyXG5cdFx0cmV0dXJuIG0uZGlmZihtaWRuaWdodCwgJ21pbnV0ZXMnKTtcclxuXHR9XHJcblxyXG5cdHN0YXRpYyBnZXRNaW51dGVzQmV0d2VlbihzdGFydDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQsIGVuZDogRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpIHtcclxuXHRcdGNvbnN0IG0gPSBtb21lbnQoc3RhcnQpO1xyXG5cdFx0Y29uc3QgbTIgPSBtb21lbnQoZW5kKTtcclxuXHRcdHJldHVybiBtMi5kaWZmKG0sICdtaW51dGVzJyk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBQYXJzZSBqc29uIHN0cmluZyB3aXRoIGRhdGUgc2VyaWFsaXplZCBpbnRvIHN0cmluZywgYW5kIGdldCBwcm9wZXIgZGF0ZSBvYmplY3QgYmFja1xyXG5cdCAqIEBwYXJhbSBzXHJcblx0ICovXHJcblx0c3RhdGljIGRhdGVTYWZlSnNvblBhcnNlKHM6IHN0cmluZykge1xyXG5cdFx0cmV0dXJuIEpTT04ucGFyc2UocywgdGhpcy5kYXRlUmV2aXZlcik7XHJcblx0fVxyXG5cclxuXHRwcml2YXRlIHN0YXRpYyBkYXRlUmV2aXZlcihrZXk6IHN0cmluZywgdmFsdWU6IGFueSkge1xyXG5cdFx0aWYgKERhdGVGdW5jLmlzU2VyaWFsaXplZERhdGUodmFsdWUpKSB7XHJcblx0XHRcdHJldHVybiAobmV3IERhdGUodmFsdWUpKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBJZiBpdCdzIG5vdCBhIGRhdGUtc3RyaW5nLCB3ZSB3YW50IHRvIHJldHVybiB0aGUgdmFsdWUgYXMtaXMuIElmIHdlIGZhaWwgdG8gcmV0dXJuXHJcblx0XHQvLyBhIHZhbHVlLCBpdCB3aWxsIGJlIG9taXR0ZWQgZnJvbSB0aGUgcmVzdWx0YW50IGRhdGEgc3RydWN0dXJlLlxyXG5cdFx0cmV0dXJuICh2YWx1ZSk7XHJcblxyXG5cdH1cclxuXHJcblxyXG5cdC8vIEkgZGV0ZXJtaW5lIGlmIHRoZSBnaXZlbiB2YWx1ZSBpcyBhIHN0cmluZyB0aGF0IG1hdGNoZXMgdGhlIHNlcmlhbGl6ZWQtZGF0ZSBwYXR0ZXJuLlxyXG5cdHByaXZhdGUgc3RhdGljIGlzU2VyaWFsaXplZERhdGUodmFsdWU6IGFueSk6IGJvb2xlYW4ge1xyXG5cdFx0Ly8gRGF0ZXMgYXJlIHNlcmlhbGl6ZWQgaW4gVFogZm9ybWF0LCBleGFtcGxlOiAnMTk4MS0xMi0yMFQwNDowMDoxNC4wMDBaJy5cclxuXHRcdGNvbnN0IGRhdGVQYXR0ZXJuID0gL15cXGR7NH0tXFxkezJ9LVxcZHsyfVRcXGR7Mn06XFxkezJ9OlxcZHsyfVxcLlxcZHszfVokLztcclxuXHRcdHJldHVybiAoRGF0ZUZ1bmMuaXNTdHJpbmcodmFsdWUpICYmIGRhdGVQYXR0ZXJuLnRlc3QodmFsdWUpKTtcclxuXHR9XHJcblxyXG5cclxuXHQvLyBJIGRldGVybWluZSBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgYSBTdHJpbmcuXHJcblx0cHJpdmF0ZSBzdGF0aWMgaXNTdHJpbmcodmFsdWU6IGFueSk6IGJvb2xlYW4ge1xyXG5cdFx0cmV0dXJuICh7fS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PT0gJ1tvYmplY3QgU3RyaW5nXScpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGRhdGVTYWZlUGFyc2Uoczogc3RyaW5nIHwgRGF0ZSkge1xyXG5cdFx0Y29uc3QgbSA9IG1vbWVudChzKTtcclxuXHRcdHJldHVybiBtLnRvRGF0ZSgpO1xyXG5cdH1cclxuXHJcblx0c3RhdGljIGNvbXBvc2VEYXRlV2l0aE1pbnV0ZXMoZDogRGF0ZSwgbWludXRlOiBudW1iZXIpOiBEYXRlIHtcclxuXHRcdGNvbnN0IG0gPSBtb21lbnQoZCk7XHJcblx0XHRjb25zdCBtaWRuaWdodCA9IG1vbWVudChkKS5zdGFydE9mKCdkYXknKTsgLy8gTXV0YXRlcyB0aGUgb3JpZ2luYWwgbW9tZW50IGJ5IHNldHRpbmcgaXQgdG8gdGhlIHN0YXJ0IG9mIGEgdW5pdCBvZiB0aW1lLiBTbyBJIGhhdmUgYmV0dGVyIG5vdCB0byB1c2UgbSB3aGljaCB3aWwgYmUgY2hhbmdlZCBieSBjYWxsaW5nIHRoaXMgZnVuY3Rpb25cclxuXHRcdG1pZG5pZ2h0LmFkZChtaW51dGUsICdtaW51dGVzJyk7XHJcblx0XHRyZXR1cm4gbWlkbmlnaHQudG9EYXRlKCk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBTYWZlIGNvbXBhcmUgc2luY2UgZGF0ZSBkYXRhIG1heSBiZSBjb25zaWRlcmVkIGFzIHN0cmluZyByYXRoZXIgdGhhbiBkYXRlLlxyXG5cdCAqIEBwYXJhbSBkMVxyXG5cdCAqIEBwYXJhbSBkMlxyXG5cdCAqL1xyXG5cdHN0YXRpYyBjb21wYXJlKGQxOiBEYXRlIHwgdW5kZWZpbmVkLCBkMjogRGF0ZSB8IHVuZGVmaW5lZCk6IG51bWJlciB7XHJcblx0XHRpZiAoIWQxICYmICFkMikge1xyXG5cdFx0XHRyZXR1cm4gMDtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIWQxKSB7XHJcblx0XHRcdHJldHVybiAtTmFOXHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCFkMikge1xyXG5cdFx0XHRyZXR1cm4gTmFOO1xyXG5cdFx0fVxyXG5cclxuXHRcdGNvbnN0IGRkMSA9IChuZXcgRGF0ZShkMSkpLnZhbHVlT2YoKTtcclxuXHRcdGNvbnN0IGRkMiA9IChuZXcgRGF0ZShkMikpLnZhbHVlT2YoKTtcclxuXHRcdHJldHVybiBkZDEgLSBkZDI7XHJcblx0fVxyXG59XHJcblxyXG4iXX0=
|