@entity-access/entity-access 1.0.15 → 1.0.16

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.
@@ -0,0 +1,402 @@
1
+ import TimeSpan from "./TimeSpan.js";
2
+
3
+ /**
4
+ * DateTime differs from Date in following cases,
5
+ * 1. DateTime is immutable, however underlying object is Date
6
+ * but all methods specific to DateTime are immutable
7
+ * 2. DateTime has readonly properties for `day, month, year etc`
8
+ * 3. DateTime is derived from Date so passing DateTime to existing
9
+ * code will not change anything, however intellisense does not display
10
+ * any methods of Date unless you explicity cast as Date, but instanceof
11
+ * works correctly
12
+ * 4. DateTime does not modify underlying Date prototype or add any methods to it
13
+ * ``` typescript
14
+ * DateTime dt = DateTime.now();
15
+ * (dt instanceof Date) // is true
16
+ * (dt instanceof DateTime) // is also true
17
+ * ```
18
+ */
19
+ export default class DateTime {
20
+
21
+ /**
22
+ * Current date without time
23
+ */
24
+ public static get today(): DateTime {
25
+ const a = new DateTime();
26
+ return a.date;
27
+ }
28
+
29
+ /**
30
+ * Current UTC Date
31
+ */
32
+ public static get utcNow(): DateTime {
33
+ const now = new Date();
34
+ return new DateTime(now.getTime() + now.getTimezoneOffset());
35
+ }
36
+
37
+ /**
38
+ * DateTime at right now
39
+ */
40
+ public static get now(): DateTime {
41
+ return new DateTime();
42
+ }
43
+
44
+ /**
45
+ * Returns DateTime new instance from Date or String, if d is DateTime already
46
+ * it will return the d.
47
+ * @param d Date | DateTime | string
48
+ * @returns DateTime
49
+ */
50
+ public static from(d: Date | DateTime | string): DateTime {
51
+ if (!d) {
52
+ return null;
53
+ }
54
+ if (!(d instanceof DateTime)) {
55
+ if (d instanceof Date) {
56
+ d = new DateTime(d.getTime());
57
+ }
58
+ return new DateTime(d as any);
59
+ }
60
+ return d;
61
+ }
62
+
63
+ public static parse(s: string): DateTime {
64
+ return new DateTime(s);
65
+ }
66
+
67
+ /**
68
+ * Converts a date and time to a string by using the current or specified locale.
69
+ * @param locales A locale string or array of locale strings that contain one or more language
70
+ * or locale tags. If you include more than one locale string, list them in descending order of
71
+ * priority so that the first entry is the preferred locale. If you omit this parameter,
72
+ * the default locale of the JavaScript runtime is used.
73
+ * @param options An object that contains one or more properties that specify comparison options.
74
+ */
75
+ public toLocaleString: (locales?: string | string[], options?: Intl.DateTimeFormatOptions) => string;
76
+
77
+ /**
78
+ * Converts a date to a string by using the current or specified locale.
79
+ * @param locales A locale string or array of locale strings that contain one or more language
80
+ * or locale tags. If you include more than one locale string, list them in descending order
81
+ * of priority so that the first entry is the preferred locale. If you omit this parameter,
82
+ * the default locale of the JavaScript runtime is used.
83
+ * @param options An object that contains one or more properties that specify comparison options.
84
+ */
85
+ public toLocaleDateString: (locales?: string | string[], options?: Intl.DateTimeFormatOptions) => string;
86
+
87
+ /**
88
+ * Converts a time to a string by using the current or specified locale.
89
+ * @param locales A locale string or array of locale strings that contain one or more language
90
+ * or locale tags. If you include more than one locale string, list them in descending order of
91
+ * priority so that the first entry is the preferred locale. If you omit this parameter,
92
+ * the default locale of the JavaScript runtime is used.
93
+ * @param options An object that contains one or more properties that specify comparison options.
94
+ */
95
+ public toLocaleTimeString: (locales?: string | string[], options?: Intl.DateTimeFormatOptions) => string;
96
+
97
+ /** Returns a date converted to a string using Universal Coordinated Time (UTC). */
98
+ public toUTCString: () => string;
99
+ /** Returns a date as a string value in ISO format. */
100
+ public toISOString: () => string;
101
+
102
+ /** Used by the JSON.stringify method to enable the transformation of an object's data for JavaScript Object
103
+ * Notation (JSON) serialization.
104
+ */
105
+ public toJSON: (key?: any) => string;
106
+
107
+ public toTimeString: () => string;
108
+
109
+ public toDateString: () => string;
110
+
111
+ /** Day of month */
112
+ public get day(): number {
113
+ return (this as any as Date).getDate();
114
+ }
115
+
116
+ /** Day of week */
117
+ public get dayOfWeek(): number {
118
+ return (this as any as Date).getDay();
119
+ }
120
+
121
+ /**
122
+ * Current month, 0 is January
123
+ */
124
+ public get month(): number {
125
+ return (this as any as Date).getMonth();
126
+ }
127
+
128
+ /**
129
+ * Current full year
130
+ */
131
+ public get year(): number {
132
+ return (this as any as Date).getFullYear();
133
+ }
134
+
135
+ /**
136
+ * Current hour of the day
137
+ */
138
+ public get hour(): number {
139
+ return (this as any as Date).getHours();
140
+ }
141
+
142
+ /**
143
+ * Current minute of the hour
144
+ */
145
+ public get minute(): number {
146
+ return (this as any as Date).getMinutes();
147
+ }
148
+
149
+ /**
150
+ * Current second of the minute
151
+ */
152
+ public get second(): number {
153
+ return (this as any as Date).getSeconds();
154
+ }
155
+
156
+ public get milliSecond(): number {
157
+ return (this as any as Date).getMilliseconds();
158
+ }
159
+
160
+ /**
161
+ * Timezone offset as TimeSpan
162
+ */
163
+ public get timeZoneOffset(): TimeSpan {
164
+ return TimeSpan.fromMinutes((this as any as Date).getTimezoneOffset());
165
+ }
166
+
167
+ /**
168
+ * Milliseconds since EPOCH, ie total number of milliseconds
169
+ * of underlying Date object
170
+ */
171
+ public get msSinceEpoch(): number {
172
+ return (this as any as Date).getTime();
173
+ }
174
+
175
+ /**
176
+ * Strips time of the day and returns Date only
177
+ */
178
+ public get date(): DateTime {
179
+ const d = new DateTime(
180
+ (this as any as Date).getFullYear(),
181
+ (this as any as Date).getMonth(),
182
+ (this as any as Date).getDate(), 0, 0, 0, 0);
183
+ return d;
184
+ }
185
+
186
+ /**
187
+ * Just for convenience, avoid using this, instead use methods of DateTime
188
+ * or suggest better method at our github repo
189
+ */
190
+ public get asJSDate(): Date {
191
+ return (this as any as Date);
192
+ }
193
+
194
+ /**
195
+ * Gets time of the day in TimeSpan format
196
+ */
197
+ public get time(): TimeSpan {
198
+ return new TimeSpan(
199
+ 0,
200
+ (this as any as Date).getHours(),
201
+ (this as any as Date).getMinutes(),
202
+ (this as any as Date).getSeconds(),
203
+ (this as any as Date).getMilliseconds());
204
+ }
205
+
206
+ /**
207
+ * Creates new DateTime instance from given input,
208
+ * input parameters are exactly same as `Date`
209
+ */
210
+ constructor(
211
+ a?: any | string, b?: number, c?: number, d?: number,
212
+ e?: number, f?: number, g?: number) {
213
+ let rd: any;
214
+ switch (arguments.length) {
215
+ case 0:
216
+ rd = new Date() as any;
217
+ break;
218
+ case 1:
219
+ rd = new Date(a) as any;
220
+ break;
221
+ case 2:
222
+ rd = new Date(a, b) as any;
223
+ break;
224
+ case 3:
225
+ rd = new Date(a, b, c) as any;
226
+ break;
227
+ case 4:
228
+ rd = new Date(a, b, c, d) as any;
229
+ break;
230
+ case 5:
231
+ rd = new Date(a, b, c, d, e) as any;
232
+ break;
233
+ case 6:
234
+ rd = new Date(a, b, c, d, e, f) as any;
235
+ break;
236
+ default:
237
+ rd = new Date(a, b, c, d, e, f, g) as any;
238
+ }
239
+ Object.setPrototypeOf(rd, DateTime.prototype);
240
+ return rd as any;
241
+ }
242
+
243
+ /**
244
+ * Adds date or TimeSpan to current date and returns a new DateTime
245
+ * @returns DateTime
246
+ * @param d DateTime or TimeSpan
247
+ */
248
+ public add(d: DateTime | TimeSpan): DateTime;
249
+
250
+ /**
251
+ * Adds (or removes -ve values specified) and returns newly created DateTime
252
+ * @returns DateTime
253
+ * @param days number of days
254
+ * @param hours number of hours
255
+ * @param minutes number of minutes
256
+ * @param seconds number of seconds
257
+ * @param milliseconds number of milliseconds
258
+ */
259
+ public add(days: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number): DateTime;
260
+ public add(
261
+ t: DateTime | TimeSpan | Date | number,
262
+ hours?: number,
263
+ minutes?: number,
264
+ seconds?: number,
265
+ milliseconds?: number): DateTime {
266
+ if (t instanceof Date) {
267
+ return new DateTime(
268
+ (this as any as Date).getTime() + t.getTime());
269
+ }
270
+ let days: number = 0;
271
+ if (t instanceof TimeSpan) {
272
+ days = t.days;
273
+ hours = t.hours;
274
+ minutes = t.minutes;
275
+ seconds = t.seconds;
276
+ milliseconds = t.milliseconds;
277
+ } else {
278
+ days = t as number;
279
+ }
280
+ function hasValue(n: number | undefined | null, name: string ): boolean {
281
+ if (n === undefined) {
282
+ return false;
283
+ }
284
+ if (n === null) {
285
+ throw new Error(`${name} cannot be null`);
286
+ }
287
+ return n !== 0;
288
+ }
289
+ const d = new Date((this as any as Date).getTime());
290
+ if (hasValue(days, "days")) { d.setDate(d.getDate() + days); }
291
+ if (hasValue(hours, "hours")) { d.setHours(d.getHours() + hours); }
292
+ if (hasValue(minutes, "minutes")) { d.setMinutes(d.getMinutes() + minutes); }
293
+ if (hasValue(seconds, "seconds")) { d.setSeconds(d.getSeconds() + seconds); }
294
+ if (hasValue(milliseconds, "milliseconds")) { d.setMilliseconds(d.getMilliseconds() + milliseconds); }
295
+ Object.setPrototypeOf(d, DateTime.prototype);
296
+ return d as any as DateTime;
297
+ }
298
+
299
+ public addMonths(m: number): DateTime {
300
+ const d = new Date(this.msSinceEpoch);
301
+ d.setMonth(d.getMonth() + m);
302
+ Object.setPrototypeOf(d, DateTime.prototype);
303
+ return d as any;
304
+ }
305
+
306
+ public addYears(y: number): DateTime {
307
+ const d = new Date(this.msSinceEpoch);
308
+ d.setFullYear(d.getFullYear() + y);
309
+ Object.setPrototypeOf(d, DateTime.prototype);
310
+ return d as any;
311
+ }
312
+
313
+ public addDays(day: number): DateTime {
314
+ const d = new Date(this.msSinceEpoch);
315
+ d.setDate(d.getDate() + day);
316
+ Object.setPrototypeOf(d, DateTime.prototype);
317
+ return d as any;
318
+ }
319
+
320
+ public addHours(h: number): DateTime {
321
+ const d = new Date(this.msSinceEpoch);
322
+ d.setHours(d.getHours() + h);
323
+ Object.setPrototypeOf(d, DateTime.prototype);
324
+ return d as any;
325
+ }
326
+
327
+ public addMinutes(m: number): DateTime {
328
+ const d = new Date(this.msSinceEpoch);
329
+ d.setMinutes(d.getMinutes() + m);
330
+ Object.setPrototypeOf(d, DateTime.prototype);
331
+ return d as any;
332
+ }
333
+
334
+ /**
335
+ * Returns TimeSpan from subtracting rhs from this,
336
+ * `const ts = lhs.diff(rhs); // ts = lhs - rhs`
337
+ * @param rhs Right hand side
338
+ * @returns TimeSpan
339
+ */
340
+ public diff(rhs: Date | DateTime): TimeSpan {
341
+ return new TimeSpan(
342
+ (this as any as Date).getTime() - (rhs as Date).getTime());
343
+ }
344
+
345
+ public equals(d: DateTime | Date): boolean {
346
+ if (!d) { return false; }
347
+ return (this as any as Date).getTime() === (d as any as Date).getTime();
348
+ }
349
+
350
+ /**
351
+ * Trims time part and compares the given dates
352
+ * @param d date to test
353
+ */
354
+ public dateEquals(d: DateTime | Date): boolean {
355
+ if (!d) { return false; }
356
+ return this.date.equals(DateTime.from(d).date);
357
+ }
358
+
359
+ public compare(d: DateTime | Date): number {
360
+ return (this as any as Date).getTime() - (d as any as Date).getTime();
361
+ }
362
+
363
+ public toRelativeString(dt?: DateTime | Date): string {
364
+ if (!dt) {
365
+ dt = DateTime.now;
366
+ } else {
367
+ if (dt instanceof Date && !(dt instanceof DateTime)) {
368
+ (dt as any).__proto__ = DateTime.prototype;
369
+ dt = (dt as any) as DateTime;
370
+ }
371
+ }
372
+
373
+ const diff = this.diff(dt);
374
+ if (dt.year !== this.year) {
375
+ return this.toLocaleDateString();
376
+ }
377
+
378
+ if (Math.abs(diff.totalDays) > 6) {
379
+ return this.toLocaleDateString(undefined, { month: "short", day: "numeric" });
380
+ }
381
+
382
+ if (Math.abs(diff.totalHours) > 23) {
383
+ return this.toLocaleDateString(undefined, { weekday: "short" });
384
+ }
385
+
386
+ if (Math.abs(diff.totalMinutes) > 59) {
387
+ return `${ Math.floor(diff.totalHours) } hours`;
388
+ }
389
+
390
+ return `${Math.floor(diff.totalMinutes)} mins`;
391
+ }
392
+
393
+ /**
394
+ * Returns number so that DateTime in logical comparison
395
+ * returns correct answer. Such as DateTime.from("2022-02-01") > DateTime.from("2021-02-01") returns true.
396
+ * @returns Milliseconds since EPOCH
397
+ */
398
+ public valueOf() {
399
+ return (this as any as Date).getTime();
400
+ }
401
+
402
+ }
@@ -0,0 +1,222 @@
1
+ function isEmpty(n: number): boolean {
2
+ return n === undefined || n === null || n === 0 || isNaN(n);
3
+ }
4
+
5
+ export const msMinutes = 60000;
6
+
7
+ export const msSeconds = 1000;
8
+
9
+ export const msHours = 3600000;
10
+
11
+ export const msDays = 24 * msHours;
12
+
13
+ /**
14
+ * This is due to performance reason, copied from Source of TimeSpan from C# code.
15
+ */
16
+ const daysPerMS = 1 / msDays;
17
+
18
+ const hoursPerMS = 1 / msHours;
19
+
20
+ const minutesPerMS = 1 / msMinutes;
21
+
22
+ const secondsPerMS = 1 / msSeconds;
23
+
24
+ function padLeft(n: number, c: number = 2, t: string = "0"): string {
25
+ let s = n.toString();
26
+ if (s.length < c) {
27
+ s = t + s;
28
+ }
29
+ return s;
30
+ }
31
+
32
+ export default class TimeSpan {
33
+
34
+ public static fromDays(n: number): TimeSpan {
35
+ return new TimeSpan(n * msDays);
36
+ }
37
+
38
+ public static fromHours(n: number): TimeSpan {
39
+ return new TimeSpan(n * msHours);
40
+ }
41
+
42
+ public static fromMinutes(n: number): TimeSpan {
43
+ return new TimeSpan(n * msMinutes);
44
+ }
45
+
46
+ public static fromSeconds(n: number): TimeSpan {
47
+ return new TimeSpan(n * msSeconds);
48
+ }
49
+
50
+ public static parse(text: string): TimeSpan {
51
+ if (!text) {
52
+ throw new Error("Invalid time format");
53
+ }
54
+ let isPM: boolean = false;
55
+ // tslint:disable-next-line: one-variable-per-declaration
56
+ let d: number, h: number, m: number, s: number, ms: number;
57
+ const tokens = text.split(/:/);
58
+ // split last...
59
+ const last = tokens[tokens.length - 1];
60
+ const lastParts = last.split(" ");
61
+ if (lastParts.length > 1) {
62
+ if (/pm/i.test(lastParts[1])) {
63
+ isPM = true;
64
+ }
65
+ tokens[tokens.length - 1] = lastParts[0];
66
+ }
67
+ const firstOfLast = lastParts[0];
68
+ if (firstOfLast.indexOf(".") !== -1) {
69
+ // it has ms...
70
+ const secondParts = firstOfLast.split(".");
71
+ if (secondParts.length > 1) {
72
+ tokens[tokens.length - 1] = secondParts[0];
73
+ ms = parseInt(secondParts[1], 10);
74
+ }
75
+ }
76
+
77
+ if (tokens.length === 2) {
78
+ // this is hour:min
79
+ d = 0;
80
+ h = parseInt(tokens[0], 10);
81
+ m = parseInt(tokens[1], 10);
82
+ } else if (tokens.length === 3) {
83
+ d = 0;
84
+ h = parseInt(tokens[0], 10);
85
+ m = parseInt(tokens[1], 10);
86
+ s = parseInt(tokens[2], 10);
87
+ } else if (tokens.length === 4) {
88
+ d = parseInt(tokens[0], 10);
89
+ h = parseInt(tokens[1], 10);
90
+ m = parseInt(tokens[2], 10);
91
+ s = parseInt(tokens[3], 10);
92
+ }
93
+
94
+ return new TimeSpan(d, isPM ? h + 12 : h, m, s, ms);
95
+ }
96
+
97
+ private msSinceEpoch: number;
98
+
99
+ public get totalSeconds(): number {
100
+ return this.msSinceEpoch * secondsPerMS;
101
+ }
102
+
103
+ public get totalMinutes(): number {
104
+ return this.msSinceEpoch * minutesPerMS;
105
+ }
106
+
107
+ public get totalHours(): number {
108
+ return this.msSinceEpoch * hoursPerMS;
109
+ }
110
+
111
+ public get totalDays(): number {
112
+ return this.msSinceEpoch * daysPerMS;
113
+ }
114
+
115
+ public get totalMilliseconds(): number {
116
+ return this.msSinceEpoch;
117
+ }
118
+
119
+ public get days(): number {
120
+ return Math.floor(this.msSinceEpoch / msDays);
121
+ }
122
+
123
+ public get hours(): number {
124
+ return Math.floor((this.msSinceEpoch / msHours) % 24);
125
+ }
126
+
127
+ public get minutes(): number {
128
+ return Math.floor((this.msSinceEpoch / msMinutes) % 60);
129
+ }
130
+
131
+ public get seconds(): number {
132
+ return Math.floor((this.msSinceEpoch / msSeconds) % 60);
133
+ }
134
+
135
+ public get milliseconds(): number {
136
+ return Math.floor(this.msSinceEpoch % 1000);
137
+ }
138
+
139
+ /**
140
+ * Duration is always positive TimeSpan
141
+ */
142
+ public get duration(): TimeSpan {
143
+ const t = this.msSinceEpoch;
144
+ return new TimeSpan(t > 0 ? t : -t);
145
+ }
146
+
147
+ /**
148
+ * Removes days and only trims given TimeSpan to TimeOfDay
149
+ */
150
+ public get trimmedTime(): TimeSpan {
151
+ return new TimeSpan(Math.ceil(this.msSinceEpoch % msDays));
152
+ }
153
+
154
+ constructor(ms: number);
155
+ // tslint:disable-next-line: unified-signatures
156
+ constructor(days: number, hours: number, minutes?: number, seconds?: number, milliseconds?: number)
157
+ constructor(days: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number) {
158
+ if (arguments.length === 1) {
159
+ this.msSinceEpoch = days;
160
+ } else {
161
+ this.msSinceEpoch =
162
+ (days || 0) * msDays +
163
+ (hours || 0) * msHours +
164
+ (minutes || 0) * msMinutes +
165
+ (seconds || 0) * msSeconds +
166
+ (milliseconds || 0);
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Format the TimeSpan as time format
172
+ * @param formatAs12 Display time as 12 hours with AM/PM (only if day is zero)
173
+ */
174
+ public toString(formatAs12: boolean = false): string {
175
+
176
+ let ams = this.msSinceEpoch;
177
+
178
+ const text = [];
179
+ let postFix = "";
180
+
181
+ function format(max: number, f12: boolean = false) {
182
+ let txt = null;
183
+ if (ams > max) {
184
+ const n = Math.floor(ams / max);
185
+ ams = ams % max;
186
+ if (f12) {
187
+ if (n > 12) {
188
+ postFix = " PM";
189
+ txt = padLeft(n - 12);
190
+ } else {
191
+ postFix = " AM";
192
+ }
193
+ }
194
+ if (!txt) {
195
+ txt = padLeft(n);
196
+ }
197
+ }
198
+ if (txt) {
199
+ text.push(txt);
200
+ }
201
+ return txt;
202
+ }
203
+
204
+ const d = format(msDays);
205
+ format(msHours, formatAs12 && !d);
206
+ format(msMinutes);
207
+ let s = format(msSeconds);
208
+ if (ams) {
209
+ s += "." + ams;
210
+ text[text.length - 1] = s;
211
+ }
212
+ return `${text.join(":")}${postFix}`;
213
+ }
214
+
215
+ public add(ts: TimeSpan): TimeSpan {
216
+ return new TimeSpan(this.msSinceEpoch + ts.msSinceEpoch);
217
+ }
218
+
219
+ public equals(ts: TimeSpan): boolean {
220
+ return ts.msSinceEpoch === this.msSinceEpoch;
221
+ }
222
+ }