@fable-org/fable-library-ts 1.0.0-beta-001

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.
Files changed (57) hide show
  1. package/Array.ts +1362 -0
  2. package/Async.ts +207 -0
  3. package/AsyncBuilder.ts +222 -0
  4. package/BigInt.ts +337 -0
  5. package/BitConverter.ts +165 -0
  6. package/Boolean.ts +22 -0
  7. package/CHANGELOG.md +15 -0
  8. package/Char.ts +222 -0
  9. package/Choice.ts +300 -0
  10. package/Date.ts +495 -0
  11. package/DateOffset.ts +324 -0
  12. package/DateOnly.ts +146 -0
  13. package/Decimal.ts +250 -0
  14. package/Double.ts +55 -0
  15. package/Encoding.ts +170 -0
  16. package/Event.ts +119 -0
  17. package/FSharp.Collections.ts +34 -0
  18. package/FSharp.Core.CompilerServices.ts +37 -0
  19. package/FSharp.Core.ts +86 -0
  20. package/Global.ts +37 -0
  21. package/Guid.ts +143 -0
  22. package/Int32.ts +156 -0
  23. package/List.ts +1417 -0
  24. package/Long.ts +49 -0
  25. package/MailboxProcessor.ts +125 -0
  26. package/Map.ts +1552 -0
  27. package/MapUtil.ts +120 -0
  28. package/MutableMap.ts +344 -0
  29. package/MutableSet.ts +248 -0
  30. package/Native.ts +11 -0
  31. package/Numeric.ts +80 -0
  32. package/Observable.ts +156 -0
  33. package/Option.ts +137 -0
  34. package/README.md +3 -0
  35. package/Random.ts +196 -0
  36. package/Range.ts +56 -0
  37. package/Reflection.ts +539 -0
  38. package/RegExp.ts +143 -0
  39. package/Result.ts +196 -0
  40. package/Seq.ts +1526 -0
  41. package/Seq2.ts +129 -0
  42. package/Set.ts +1955 -0
  43. package/String.ts +589 -0
  44. package/System.Collections.Generic.ts +380 -0
  45. package/System.Text.ts +137 -0
  46. package/SystemException.ts +7 -0
  47. package/TimeOnly.ts +131 -0
  48. package/TimeSpan.ts +194 -0
  49. package/Timer.ts +80 -0
  50. package/Types.ts +231 -0
  51. package/Unicode.13.0.0.ts +4 -0
  52. package/Uri.ts +206 -0
  53. package/Util.ts +928 -0
  54. package/lib/big.d.ts +338 -0
  55. package/lib/big.js +1054 -0
  56. package/package.json +24 -0
  57. package/tsconfig.json +103 -0
package/Date.ts ADDED
@@ -0,0 +1,495 @@
1
+ /**
2
+ * DateTimeOffset functions.
3
+ *
4
+ * Note: Date instances are always DateObjects in local
5
+ * timezone (because JS dates are all kinds of messed up).
6
+ * A local date returns UTC epoch when `.getTime()` is called.
7
+ *
8
+ * Basically; invariant: date.getTime() always return UTC time.
9
+ */
10
+
11
+ import { int64, toInt64, toFloat64 } from "./BigInt.js";
12
+ import { FSharpRef } from "./Types.js";
13
+ import { compareDates, DateKind, dateOffset, IDateTime, IDateTimeOffset, padWithZeros } from "./Util.js";
14
+
15
+ export type OffsetInMinutes = number;
16
+ export type Offset = "Z" | OffsetInMinutes | null;
17
+
18
+ export function kind(value: IDateTime): number {
19
+ return value.kind || 0;
20
+ }
21
+
22
+ export function unixEpochMillisecondsToTicks(ms: number, offset: number): int64 {
23
+ return toInt64(((BigInt(ms) + 62135596800000n) + BigInt(offset)) * 10000n);
24
+ }
25
+
26
+ export function ticksToUnixEpochMilliseconds(ticks: number | bigint): number {
27
+ return Number(((BigInt(ticks) / 10000n) - 62135596800000n));
28
+ }
29
+
30
+ export function dateOffsetToString(offset: number) {
31
+ const isMinus = offset < 0;
32
+ offset = Math.abs(offset);
33
+ const hours = ~~(offset / 3600000);
34
+ const minutes = (offset % 3600000) / 60000;
35
+ return (isMinus ? "-" : "+") +
36
+ padWithZeros(hours, 2) + ":" +
37
+ padWithZeros(minutes, 2);
38
+ }
39
+
40
+ export function dateToHalfUTCString(date: IDateTime, half: "first" | "second") {
41
+ const str = date.toISOString();
42
+ return half === "first"
43
+ ? str.substring(0, str.indexOf("T"))
44
+ : str.substring(str.indexOf("T") + 1, str.length - 1);
45
+ }
46
+
47
+ function dateToISOString(d: IDateTime, utc: boolean) {
48
+ if (utc) {
49
+ return d.toISOString();
50
+ } else {
51
+ // JS Date is always local
52
+ const printOffset = d.kind == null ? true : d.kind === DateKind.Local;
53
+ return padWithZeros(d.getFullYear(), 4) + "-" +
54
+ padWithZeros(d.getMonth() + 1, 2) + "-" +
55
+ padWithZeros(d.getDate(), 2) + "T" +
56
+ padWithZeros(d.getHours(), 2) + ":" +
57
+ padWithZeros(d.getMinutes(), 2) + ":" +
58
+ padWithZeros(d.getSeconds(), 2) + "." +
59
+ padWithZeros(d.getMilliseconds(), 3) +
60
+ (printOffset ? dateOffsetToString(d.getTimezoneOffset() * -60000) : "");
61
+ }
62
+ }
63
+
64
+ function dateToISOStringWithOffset(dateWithOffset: Date, offset: number) {
65
+ const str = dateWithOffset.toISOString();
66
+ return str.substring(0, str.length - 1) + dateOffsetToString(offset);
67
+ }
68
+
69
+ function dateToStringWithCustomFormat(date: Date, format: string, utc: boolean) {
70
+ return format.replace(/(\w)\1*/g, (match: string) => {
71
+ let rep = Number.NaN;
72
+ switch (match.substring(0, 1)) {
73
+ case "y":
74
+ const y = utc ? date.getUTCFullYear() : date.getFullYear();
75
+ rep = match.length < 4 ? y % 100 : y; break;
76
+ case "M": rep = (utc ? date.getUTCMonth() : date.getMonth()) + 1; break;
77
+ case "d": rep = utc ? date.getUTCDate() : date.getDate(); break;
78
+ case "H": rep = utc ? date.getUTCHours() : date.getHours(); break;
79
+ case "h":
80
+ const h = utc ? date.getUTCHours() : date.getHours();
81
+ rep = h > 12 ? h % 12 : h; break;
82
+ case "m": rep = utc ? date.getUTCMinutes() : date.getMinutes(); break;
83
+ case "s": rep = utc ? date.getUTCSeconds() : date.getSeconds(); break;
84
+ case "f": rep = utc ? date.getUTCMilliseconds() : date.getMilliseconds(); break;
85
+ }
86
+ if (Number.isNaN(rep)) {
87
+ return match;
88
+ } else {
89
+ return padWithZeros(rep, match.length);
90
+ }
91
+ });
92
+ }
93
+
94
+ function dateToStringWithOffset(date: IDateTimeOffset, format?: string) {
95
+ const d = new Date(date.getTime() + (date.offset ?? 0));
96
+ if (typeof format !== "string") {
97
+ return d.toISOString().replace(/\.\d+/, "").replace(/[A-Z]|\.\d+/g, " ") + dateOffsetToString((date.offset ?? 0));
98
+ } else if (format.length === 1) {
99
+ switch (format) {
100
+ case "D": case "d": return dateToHalfUTCString(d, "first");
101
+ case "T": case "t": return dateToHalfUTCString(d, "second");
102
+ case "O": case "o": return dateToISOStringWithOffset(d, (date.offset ?? 0));
103
+ default: throw new Error("Unrecognized Date print format");
104
+ }
105
+ } else {
106
+ return dateToStringWithCustomFormat(d, format, true);
107
+ }
108
+ }
109
+
110
+ function dateToStringWithKind(date: IDateTime, format?: string) {
111
+ const utc = date.kind === DateKind.UTC;
112
+ if (typeof format !== "string") {
113
+ return utc ? date.toUTCString() : date.toLocaleString();
114
+ } else if (format.length === 1) {
115
+ switch (format) {
116
+ case "D": case "d":
117
+ return utc ? dateToHalfUTCString(date, "first") : date.toLocaleDateString();
118
+ case "T": case "t":
119
+ return utc ? dateToHalfUTCString(date, "second") : date.toLocaleTimeString();
120
+ case "O": case "o":
121
+ return dateToISOString(date, utc);
122
+ default:
123
+ throw new Error("Unrecognized Date print format");
124
+ }
125
+ } else {
126
+ return dateToStringWithCustomFormat(date, format, utc);
127
+ }
128
+ }
129
+
130
+ export function toString(date: IDateTime | IDateTimeOffset, format?: string, _provider?: any) {
131
+ return (date as IDateTimeOffset).offset != null
132
+ ? dateToStringWithOffset(date, format)
133
+ : dateToStringWithKind(date, format);
134
+ }
135
+
136
+ export function DateTime(value: number, kind?: DateKind) {
137
+ const d = new Date(value) as IDateTime;
138
+ d.kind = (kind == null ? DateKind.Unspecified : kind) | 0;
139
+ return d;
140
+ }
141
+
142
+ export function fromTicks(ticks: number | bigint, kind?: DateKind) {
143
+ kind = kind != null ? kind : DateKind.Local; // better default than Unspecified
144
+ let date = DateTime(ticksToUnixEpochMilliseconds(ticks), kind);
145
+
146
+ // Ticks are local to offset (in this case, either UTC or Local/Unknown).
147
+ // If kind is anything but UTC, that means that the tick number was not
148
+ // in utc, thus getTime() cannot return UTC, and needs to be shifted.
149
+ if (kind !== DateKind.UTC) {
150
+ date = DateTime(date.getTime() - dateOffset(date), kind);
151
+ }
152
+
153
+ return date;
154
+ }
155
+
156
+ export function fromDateTimeOffset(date: IDateTimeOffset, kind: DateKind) {
157
+ switch (kind) {
158
+ case DateKind.UTC: return DateTime(date.getTime(), DateKind.UTC);
159
+ case DateKind.Local: return DateTime(date.getTime(), DateKind.Local);
160
+ default:
161
+ const d = DateTime(date.getTime() + (date.offset ?? 0), kind);
162
+ return DateTime(d.getTime() - dateOffset(d), kind);
163
+ }
164
+ }
165
+
166
+ export function getTicks(date: IDateTime | IDateTimeOffset) {
167
+ return unixEpochMillisecondsToTicks(date.getTime(), dateOffset(date));
168
+ }
169
+
170
+ export function minValue() {
171
+ // This is "0001-01-01T00:00:00.000Z", actual JS min value is -8640000000000000
172
+ return DateTime(-62135596800000, DateKind.Unspecified);
173
+ }
174
+
175
+ export function maxValue() {
176
+ // This is "9999-12-31T23:59:59.999Z", actual JS max value is 8640000000000000
177
+ return DateTime(253402300799999, DateKind.Unspecified);
178
+ }
179
+
180
+ export function parseRaw(input: string): [Date, Offset] {
181
+ function fail() {
182
+ throw new Error(`The string is not a valid Date: ${input}`);
183
+ }
184
+
185
+ if (input == null || input.trim() === "") {
186
+ fail();
187
+ }
188
+
189
+ // ISO dates without TZ are parsed as UTC. Adding time without TZ keeps them local.
190
+ if (input.length === 10 && input[4] === "-" && input[7] === "-") {
191
+ input += "T00:00:00";
192
+ }
193
+ let date = new Date(input);
194
+ let offset: Offset = null;
195
+
196
+ if (isNaN(date.getTime())) {
197
+ // Try to check strings JS Date cannot parse (see #1045, #1422)
198
+ // tslint:disable-next-line:max-line-length
199
+ const m = /^\s*(\d+[^\w\s:]\d+[^\w\s:]\d+)?\s*(\d+:\d+(?::\d+(?:\.\d+)?)?)?\s*([AaPp][Mm])?\s*(Z|[+-]([01]?\d):?([0-5]?\d)?)?\s*$/.exec(input);
200
+ if (m != null) {
201
+ let baseDate: Date;
202
+ let timeInSeconds = 0;
203
+ if (m[2] != null) {
204
+ const timeParts = m[2].split(":");
205
+ const hourPart = parseInt(timeParts[0], 10);
206
+ timeInSeconds =
207
+ hourPart * 3600 +
208
+ parseInt(timeParts[1] || "0", 10) * 60 +
209
+ parseFloat(timeParts[2] || "0");
210
+ if (m[3] != null && m[3].toUpperCase() === "PM" && hourPart < 12) {
211
+ timeInSeconds += 720;
212
+ }
213
+ }
214
+ if (m[4] != null) { // There's an offset, parse as UTC
215
+ if (m[1] != null) {
216
+ baseDate = new Date(m[1] + " UTC");
217
+ } else {
218
+ const d = new Date();
219
+ baseDate = new Date(d.getUTCFullYear() + "/" + (d.getUTCMonth() + 1) + "/" + d.getUTCDate());
220
+ }
221
+ if (m[4] === "Z") {
222
+ offset = "Z";
223
+ } else {
224
+ let offsetInMinutes = parseInt(m[5], 10) * 60 + parseInt(m[6] || "0", 10);
225
+ if (m[4][0] === "-") {
226
+ offsetInMinutes *= -1;
227
+ }
228
+ offset = offsetInMinutes;
229
+ timeInSeconds -= offsetInMinutes * 60;
230
+ }
231
+ } else {
232
+ if (m[1] != null) {
233
+ baseDate = new Date(m[1]);
234
+ } else {
235
+ const d = new Date();
236
+ baseDate = new Date(d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate());
237
+ }
238
+ }
239
+ date = new Date(baseDate.getTime() + timeInSeconds * 1000);
240
+ // correct for daylight savings time
241
+ date = new Date(date.getTime() + (date.getTimezoneOffset() - baseDate.getTimezoneOffset()) * 60000);
242
+ } else {
243
+ fail();
244
+ }
245
+
246
+ // Check again the date is valid after transformations, see #2229
247
+ if (isNaN(date.getTime())) {
248
+ fail();
249
+ }
250
+ }
251
+
252
+ return [date, offset];
253
+ }
254
+
255
+ export function parse(str: string, detectUTC = false): IDateTime {
256
+ const [date, offset] = parseRaw(str);
257
+ // .NET always parses DateTime as Local if there's offset info (even "Z")
258
+ // Newtonsoft.Json uses UTC if the offset is "Z"
259
+ const kind = offset != null
260
+ ? (detectUTC && offset === "Z" ? DateKind.UTC : DateKind.Local)
261
+ : DateKind.Unspecified;
262
+ return DateTime(date.getTime(), kind);
263
+ }
264
+
265
+ export function tryParse(v: string, defValue: FSharpRef<IDateTime>): boolean {
266
+ try {
267
+ defValue.contents = parse(v);
268
+ return true;
269
+ } catch (_err) {
270
+ return false;
271
+ }
272
+ }
273
+
274
+ export function create(
275
+ year: number, month: number, day: number,
276
+ h: number = 0, m: number = 0, s: number = 0,
277
+ ms: number = 0, kind?: DateKind) {
278
+ const date = kind === DateKind.UTC
279
+ ? new Date(Date.UTC(year, month - 1, day, h, m, s, ms))
280
+ : new Date(year, month - 1, day, h, m, s, ms);
281
+ if (year <= 99) {
282
+ if (kind === DateKind.UTC) {
283
+ date.setUTCFullYear(year, month - 1, day);
284
+ } else {
285
+ date.setFullYear(year, month - 1, day);
286
+ }
287
+ }
288
+ const dateValue = date.getTime();
289
+ if (isNaN(dateValue)) {
290
+ throw new Error("The parameters describe an unrepresentable Date.");
291
+ }
292
+ return DateTime(dateValue, kind);
293
+ }
294
+
295
+ export function now() {
296
+ return DateTime(Date.now(), DateKind.Local);
297
+ }
298
+
299
+ export function utcNow() {
300
+ return DateTime(Date.now(), DateKind.UTC);
301
+ }
302
+
303
+ export function today() {
304
+ return date(now());
305
+ }
306
+
307
+ export function isLeapYear(year: number) {
308
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
309
+ }
310
+
311
+ export function daysInMonth(year: number, month: number) {
312
+ return month === 2
313
+ ? (isLeapYear(year) ? 29 : 28)
314
+ : (month >= 8 ? (month % 2 === 0 ? 31 : 30) : (month % 2 === 0 ? 30 : 31));
315
+ }
316
+
317
+ export function toUniversalTime(date: IDateTime) {
318
+ return date.kind === DateKind.UTC ? date : DateTime(date.getTime(), DateKind.UTC);
319
+ }
320
+
321
+ export function toLocalTime(date: IDateTime) {
322
+ return date.kind === DateKind.Local ? date : DateTime(date.getTime(), DateKind.Local);
323
+ }
324
+
325
+ export function specifyKind(d: IDateTime, kind: DateKind) {
326
+ return create(year(d), month(d), day(d), hour(d), minute(d), second(d), millisecond(d), kind);
327
+ }
328
+
329
+ export function timeOfDay(d: IDateTime) {
330
+ return hour(d) * 3600000
331
+ + minute(d) * 60000
332
+ + second(d) * 1000
333
+ + millisecond(d);
334
+ }
335
+
336
+ export function date(d: IDateTime) {
337
+ return create(year(d), month(d), day(d), 0, 0, 0, 0, d.kind);
338
+ }
339
+
340
+ export function day(d: IDateTime) {
341
+ return d.kind === DateKind.UTC ? d.getUTCDate() : d.getDate();
342
+ }
343
+
344
+ export function hour(d: IDateTime) {
345
+ return d.kind === DateKind.UTC ? d.getUTCHours() : d.getHours();
346
+ }
347
+
348
+ export function millisecond(d: IDateTime) {
349
+ return d.kind === DateKind.UTC ? d.getUTCMilliseconds() : d.getMilliseconds();
350
+ }
351
+
352
+ export function minute(d: IDateTime) {
353
+ return d.kind === DateKind.UTC ? d.getUTCMinutes() : d.getMinutes();
354
+ }
355
+
356
+ export function month(d: IDateTime) {
357
+ return (d.kind === DateKind.UTC ? d.getUTCMonth() : d.getMonth()) + 1;
358
+ }
359
+
360
+ export function second(d: IDateTime) {
361
+ return d.kind === DateKind.UTC ? d.getUTCSeconds() : d.getSeconds();
362
+ }
363
+
364
+ export function year(d: IDateTime) {
365
+ return d.kind === DateKind.UTC ? d.getUTCFullYear() : d.getFullYear();
366
+ }
367
+
368
+ export function dayOfWeek(d: IDateTime) {
369
+ return d.kind === DateKind.UTC ? d.getUTCDay() : d.getDay();
370
+ }
371
+
372
+ export function dayOfYear(d: IDateTime) {
373
+ const _year = year(d);
374
+ const _month = month(d);
375
+ let _day = day(d);
376
+ for (let i = 1; i < _month; i++) {
377
+ _day += daysInMonth(_year, i);
378
+ }
379
+ return _day;
380
+ }
381
+
382
+ export function add(d: IDateTime, ts: number) {
383
+ const newDate = DateTime(d.getTime() + ts, d.kind);
384
+ if (d.kind === DateKind.Local) {
385
+ const oldTzOffset = d.getTimezoneOffset();
386
+ const newTzOffset = newDate.getTimezoneOffset();
387
+ return oldTzOffset !== newTzOffset
388
+ ? DateTime(newDate.getTime() + (newTzOffset - oldTzOffset) * 60000, d.kind)
389
+ : newDate;
390
+ } else {
391
+ return newDate;
392
+ }
393
+ }
394
+
395
+ export function addDays(d: IDateTime, v: number) {
396
+ return add(d, v * 86400000);
397
+ }
398
+
399
+ export function addHours(d: IDateTime, v: number) {
400
+ return add(d, v * 3600000);
401
+ }
402
+
403
+ export function addMinutes(d: IDateTime, v: number) {
404
+ return add(d, v * 60000);
405
+ }
406
+
407
+ export function addSeconds(d: IDateTime, v: number) {
408
+ return add(d, v * 1000);
409
+ }
410
+
411
+ export function addMilliseconds(d: IDateTime, v: number) {
412
+ return add(d, v);
413
+ }
414
+
415
+ export function addTicks(d: IDateTime, v: int64) {
416
+ return add(d, toFloat64(v / 10000n));
417
+ }
418
+
419
+ export function addYears(d: IDateTime, v: number) {
420
+ const newMonth = month(d);
421
+ const newYear = year(d) + v;
422
+ const _daysInMonth = daysInMonth(newYear, newMonth);
423
+ const newDay = Math.min(_daysInMonth, day(d));
424
+ return create(newYear, newMonth, newDay, hour(d), minute(d), second(d),
425
+ millisecond(d), d.kind);
426
+ }
427
+
428
+ export function addMonths(d: IDateTime, v: number) {
429
+ let newMonth = month(d) + v;
430
+ let newMonth_ = 0;
431
+ let yearOffset = 0;
432
+ if (newMonth > 12) {
433
+ newMonth_ = newMonth % 12;
434
+ yearOffset = Math.floor(newMonth / 12);
435
+ newMonth = newMonth_;
436
+ } else if (newMonth < 1) {
437
+ newMonth_ = 12 + newMonth % 12;
438
+ yearOffset = Math.floor(newMonth / 12) + (newMonth_ === 12 ? -1 : 0);
439
+ newMonth = newMonth_;
440
+ }
441
+ const newYear = year(d) + yearOffset;
442
+ const _daysInMonth = daysInMonth(newYear, newMonth);
443
+ const newDay = Math.min(_daysInMonth, day(d));
444
+ return create(newYear, newMonth, newDay, hour(d), minute(d), second(d),
445
+ millisecond(d), d.kind);
446
+ }
447
+
448
+ export function subtract<Input extends number | IDateTime, Output = Input extends number ? IDateTime : number>(d: IDateTime, that: Input): Output {
449
+ return typeof that === "number"
450
+ ? add(d, -that) as Output
451
+ : d.getTime() - that.getTime() as Output;
452
+ }
453
+
454
+ export function toLongDateString(d: IDateTime) {
455
+ return d.toDateString();
456
+ }
457
+
458
+ export function toShortDateString(d: IDateTime) {
459
+ return d.toLocaleDateString();
460
+ }
461
+
462
+ export function toLongTimeString(d: IDateTime) {
463
+ return d.toLocaleTimeString();
464
+ }
465
+
466
+ export function toShortTimeString(d: IDateTime) {
467
+ return d.toLocaleTimeString().replace(/:\d\d(?!:)/, "");
468
+ }
469
+
470
+ export function equals(d1: IDateTime, d2: IDateTime) {
471
+ return d1.getTime() === d2.getTime();
472
+ }
473
+
474
+ export const compare = compareDates;
475
+ export const compareTo = compareDates;
476
+
477
+ export function op_Addition(x: IDateTime, y: number) {
478
+ return add(x, y);
479
+ }
480
+
481
+ export function op_Subtraction<Input extends number | IDateTime, Output = Input extends number ? IDateTime : number>(x: IDateTime, y: Input): Output {
482
+ return subtract(x, y);
483
+ }
484
+
485
+ export function isDaylightSavingTime(x: IDateTime) {
486
+ const jan = new Date(x.getFullYear(), 0, 1);
487
+ const jul = new Date(x.getFullYear(), 6, 1);
488
+ return isDST(jan.getTimezoneOffset(), jul.getTimezoneOffset(), x.getTimezoneOffset());
489
+ }
490
+
491
+ function isDST(janOffset: number, julOffset: number, tOffset: number) {
492
+ return Math.min(janOffset, julOffset) === tOffset;
493
+ }
494
+
495
+ export default DateTime;