@nextera.one/tps-standard 0.5.34 → 0.6.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +133 -56
  3. package/dist/driver-manager.d.ts +34 -0
  4. package/dist/driver-manager.js +53 -0
  5. package/dist/driver-manager.js.map +1 -0
  6. package/dist/drivers/chinese.d.ts +25 -0
  7. package/dist/drivers/chinese.js +485 -0
  8. package/dist/drivers/chinese.js.map +1 -0
  9. package/dist/esm/date.js +170 -0
  10. package/dist/esm/date.js.map +1 -0
  11. package/dist/esm/driver-manager.js +49 -0
  12. package/dist/esm/driver-manager.js.map +1 -0
  13. package/dist/esm/drivers/chinese.js +481 -0
  14. package/dist/esm/drivers/chinese.js.map +1 -0
  15. package/dist/esm/drivers/gregorian.js +160 -0
  16. package/dist/esm/drivers/gregorian.js.map +1 -0
  17. package/dist/esm/drivers/hijri.js +184 -0
  18. package/dist/esm/drivers/hijri.js.map +1 -0
  19. package/dist/esm/drivers/holocene.js +115 -0
  20. package/dist/esm/drivers/holocene.js.map +1 -0
  21. package/dist/esm/drivers/julian.js +161 -0
  22. package/dist/esm/drivers/julian.js.map +1 -0
  23. package/dist/esm/drivers/persian.js +190 -0
  24. package/dist/esm/drivers/persian.js.map +1 -0
  25. package/dist/esm/drivers/tps.js +181 -0
  26. package/dist/esm/drivers/tps.js.map +1 -0
  27. package/dist/esm/drivers/unix.js +50 -0
  28. package/dist/esm/drivers/unix.js.map +1 -0
  29. package/dist/esm/index.js +873 -0
  30. package/dist/esm/index.js.map +1 -0
  31. package/dist/esm/types.js +28 -0
  32. package/dist/esm/types.js.map +1 -0
  33. package/dist/esm/uid.js +221 -0
  34. package/dist/esm/uid.js.map +1 -0
  35. package/dist/esm/utils/calendar.js +126 -0
  36. package/dist/esm/utils/calendar.js.map +1 -0
  37. package/dist/esm/utils/env.js +76 -0
  38. package/dist/esm/utils/env.js.map +1 -0
  39. package/dist/esm/utils/timezone.js +168 -0
  40. package/dist/esm/utils/timezone.js.map +1 -0
  41. package/dist/esm/utils/tps-string.js +160 -0
  42. package/dist/esm/utils/tps-string.js.map +1 -0
  43. package/dist/index.d.ts +91 -2
  44. package/dist/index.js +412 -132
  45. package/dist/index.js.map +1 -1
  46. package/dist/types.d.ts +19 -1
  47. package/dist/types.js +1 -0
  48. package/dist/types.js.map +1 -1
  49. package/dist/uid.js +1 -1
  50. package/dist/uid.js.map +1 -1
  51. package/dist/utils/timezone.d.ts +32 -0
  52. package/dist/utils/timezone.js +173 -0
  53. package/dist/utils/timezone.js.map +1 -0
  54. package/package.json +20 -5
  55. package/src/driver-manager.ts +54 -0
  56. package/src/drivers/chinese.ts +542 -0
  57. package/src/index.ts +379 -123
  58. package/src/types.ts +26 -2
  59. package/src/uid.ts +2 -2
  60. package/src/utils/timezone.ts +182 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Timezone Utilities
3
+ *
4
+ * Provides lightweight, zero-dependency helpers for converting between
5
+ * UTC timestamps and local timestamps in a given IANA timezone or
6
+ * fixed UTC offset.
7
+ *
8
+ * Used by `TPS.toDate()` when the parsed extensions include a `tz` key.
9
+ *
10
+ * Examples:
11
+ * tz=Asia/Tehran → IANA timezone name
12
+ * tz=+03:30 → fixed UTC offset
13
+ * tz=IRST → abbreviated names (best-effort, common ones mapped)
14
+ */
15
+ /** Map of common abbreviated timezone names to IANA names. */
16
+ const TZ_ABBR = {
17
+ // Middle East
18
+ IRST: "Asia/Tehran",
19
+ IRDT: "Asia/Tehran",
20
+ AST: "Asia/Riyadh",
21
+ AST3: "Asia/Riyadh",
22
+ // Europe
23
+ CET: "Europe/Paris",
24
+ CEST: "Europe/Paris",
25
+ EET: "Europe/Athens",
26
+ EEST: "Europe/Athens",
27
+ WET: "Europe/Lisbon",
28
+ WEST: "Europe/Lisbon",
29
+ // Americas
30
+ EST: "America/New_York",
31
+ EDT: "America/New_York",
32
+ CST: "America/Chicago",
33
+ CDT: "America/Chicago",
34
+ MST: "America/Denver",
35
+ MDT: "America/Denver",
36
+ PST: "America/Los_Angeles",
37
+ PDT: "America/Los_Angeles",
38
+ // Asia Pacific
39
+ JST: "Asia/Tokyo",
40
+ KST: "Asia/Seoul",
41
+ IST: "Asia/Kolkata",
42
+ CST8: "Asia/Shanghai",
43
+ AEST: "Australia/Sydney",
44
+ AEDT: "Australia/Sydney",
45
+ // UTC variants
46
+ UTC: "UTC",
47
+ GMT: "UTC",
48
+ Z: "UTC",
49
+ };
50
+ /**
51
+ * Parse a `tz` string into an IANA timezone name, or return null if unrecognized.
52
+ */
53
+ function resolveIANA(tz) {
54
+ if (!tz)
55
+ return null;
56
+ // Direct IANA name (e.g. "Asia/Tehran")
57
+ if (tz.includes("/"))
58
+ return tz;
59
+ // Common abbreviation lookup
60
+ const abbr = TZ_ABBR[tz.toUpperCase()];
61
+ if (abbr)
62
+ return abbr;
63
+ return null;
64
+ }
65
+ /**
66
+ * Parses a fixed offset string like "+03:30", "-05:00", "+0530" into ms.
67
+ * Returns NaN if the string is not a valid offset.
68
+ */
69
+ function parseFixedOffset(tz) {
70
+ const m = tz.match(/^([+-])(\d{1,2}):?(\d{2})$/);
71
+ if (!m)
72
+ return NaN;
73
+ const sign = m[1] === "+" ? 1 : -1;
74
+ const h = parseInt(m[2], 10);
75
+ const min = parseInt(m[3], 10);
76
+ return sign * (h * 60 + min) * 60000;
77
+ }
78
+ /**
79
+ * Returns the UTC offset in milliseconds for a given IANA timezone at a
80
+ * specific UTC moment. Uses `Intl.DateTimeFormat` for correctness.
81
+ *
82
+ * Returns 0 (UTC) if the timezone is unrecognised by the runtime.
83
+ */
84
+ function getIANAOffsetMs(ianaName, atUtcMs) {
85
+ try {
86
+ // Build a formatter that reports both UTC and local time parts
87
+ const fmt = new Intl.DateTimeFormat("en-US", {
88
+ timeZone: ianaName,
89
+ year: "numeric",
90
+ month: "2-digit",
91
+ day: "2-digit",
92
+ hour: "2-digit",
93
+ minute: "2-digit",
94
+ second: "2-digit",
95
+ hour12: false,
96
+ });
97
+ const parts = Object.fromEntries(fmt.formatToParts(new Date(atUtcMs)).map((p) => [p.type, p.value]));
98
+ // Reconstruct the local time as UTC
99
+ const localMs = Date.UTC(parseInt(parts.year), parseInt(parts.month) - 1, parseInt(parts.day), parseInt(parts.hour === "24" ? "0" : parts.hour), parseInt(parts.minute), parseInt(parts.second));
100
+ return localMs - atUtcMs;
101
+ }
102
+ catch {
103
+ return 0;
104
+ }
105
+ }
106
+ /**
107
+ * Given a UTC timestamp (ms), returns the equivalent *local* millisecond
108
+ * value for the given `tz` string.
109
+ *
110
+ * This is useful for display: `utcMs + offsetMs` gives local wall-clock time.
111
+ */
112
+ export function utcToLocal(utcMs, tz) {
113
+ // Try fixed offset first (e.g. "+03:30")
114
+ const fixed = parseFixedOffset(tz);
115
+ if (!isNaN(fixed))
116
+ return utcMs + fixed;
117
+ const iana = resolveIANA(tz);
118
+ if (!iana)
119
+ return utcMs; // Unknown tz — return UTC unchanged
120
+ return utcMs + getIANAOffsetMs(iana, utcMs);
121
+ }
122
+ /**
123
+ * Given a *local* timestamp (ms) in `tz`, returns the equivalent UTC ms.
124
+ *
125
+ * Used when converting a calendar date expressed in local time back to UTC.
126
+ */
127
+ export function localToUtc(localMs, tz) {
128
+ // Try fixed offset first
129
+ const fixed = parseFixedOffset(tz);
130
+ if (!isNaN(fixed))
131
+ return localMs - fixed;
132
+ const iana = resolveIANA(tz);
133
+ if (!iana)
134
+ return localMs;
135
+ // Approximation: compute the offset at the approximate UTC moment
136
+ // (offset iteration is overkill for a scheduling library)
137
+ const approxUtcMs = localMs - getIANAOffsetMs(iana, localMs);
138
+ // One correction pass for DST edge-cases
139
+ const correctedOffset = getIANAOffsetMs(iana, approxUtcMs);
140
+ return localMs - correctedOffset;
141
+ }
142
+ /**
143
+ * Returns the UTC offset string (e.g. "+03:30") for a given IANA timezone
144
+ * at the current moment. Useful for formatting and display.
145
+ */
146
+ export function getOffsetString(tz, atUtcMs = Date.now()) {
147
+ // Fast-path for UTC/GMT/Z
148
+ const upper = tz.toUpperCase();
149
+ if (upper === "UTC" || upper === "GMT" || upper === "Z")
150
+ return "+00:00";
151
+ const fixed = parseFixedOffset(tz);
152
+ if (!isNaN(fixed))
153
+ return tz;
154
+ const iana = resolveIANA(tz);
155
+ if (!iana)
156
+ return "+00:00";
157
+ const offsetMs = getIANAOffsetMs(iana, atUtcMs);
158
+ const sign = offsetMs >= 0 ? "+" : "-";
159
+ const abs = Math.abs(offsetMs);
160
+ const h = Math.floor(abs / 3600000)
161
+ .toString()
162
+ .padStart(2, "0");
163
+ const m = Math.floor((abs % 3600000) / 60000)
164
+ .toString()
165
+ .padStart(2, "0");
166
+ return `${sign}${h}:${m}`;
167
+ }
168
+ //# sourceMappingURL=timezone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timezone.js","sourceRoot":"","sources":["../../../src/utils/timezone.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,160 @@
1
+ import { TimeOrder, DefaultCalendars } from "../types";
2
+ /**
3
+ * Generate the canonical `T:` time string for a set of components.
4
+ */
5
+ export function buildTimePart(comp) {
6
+ const calendar = (comp.calendar || "").toLowerCase();
7
+ if (!/^[a-z]{3,4}$/.test(calendar)) {
8
+ throw new Error(`Invalid calendar code '${comp.calendar}'. Calendar code width must be 3–4 lowercase letters.`);
9
+ }
10
+ let time = `T:${calendar}`;
11
+ if (calendar === DefaultCalendars.UNIX) {
12
+ if (comp.unixSeconds !== undefined) {
13
+ time += `.s${comp.unixSeconds}`;
14
+ }
15
+ return time;
16
+ }
17
+ const tokens = [
18
+ ["m", comp.millennium, 8],
19
+ ["c", comp.century, 7],
20
+ ["y", comp.year, 6],
21
+ ["m", comp.month, 5],
22
+ ["d", comp.day, 4],
23
+ ["h", comp.hour, 3],
24
+ ["m", comp.minute, 2],
25
+ ["s", comp.second, 1],
26
+ ["m", comp.millisecond, 0],
27
+ ];
28
+ const order = comp.order || TimeOrder.DESC;
29
+ const activeTokens = order === TimeOrder.ASC ? [...tokens].reverse() : tokens;
30
+ for (const [pref, val] of activeTokens) {
31
+ if (val !== undefined) {
32
+ time += `.${pref}${val}`;
33
+ }
34
+ }
35
+ if (comp.signature) {
36
+ time += `!${comp.signature}`;
37
+ }
38
+ return time;
39
+ }
40
+ /**
41
+ * Parse the time portion of a TPS string into components.
42
+ */
43
+ export function parseTimeString(input) {
44
+ let s = input.trim();
45
+ s = s.split(/[!;?#]/)[0];
46
+ if (s.startsWith("T:"))
47
+ s = s.slice(2);
48
+ const parts = s.split(".");
49
+ if (parts.length === 0)
50
+ return null;
51
+ const calendar = parts[0];
52
+ const comp = { calendar };
53
+ const fixedRankMap = {
54
+ c: 7,
55
+ y: 6,
56
+ d: 4,
57
+ h: 3,
58
+ s: 1,
59
+ };
60
+ let initialOrder = TimeOrder.DESC;
61
+ if (calendar !== DefaultCalendars.UNIX) {
62
+ const nonMRanks = [];
63
+ for (let i = 1; i < parts.length; i++) {
64
+ const pr = parts[i]?.charAt(0);
65
+ if (pr && pr in fixedRankMap)
66
+ nonMRanks.push(fixedRankMap[pr]);
67
+ }
68
+ if (nonMRanks.length >= 2) {
69
+ const isAsc = nonMRanks.every((v, i, a) => i === 0 || a[i - 1] <= v);
70
+ if (isAsc)
71
+ initialOrder = TimeOrder.ASC;
72
+ }
73
+ }
74
+ const assignMRank = (lastRank, ord) => {
75
+ if (ord === TimeOrder.DESC) {
76
+ if (lastRank === null)
77
+ return 8;
78
+ if (lastRank > 5)
79
+ return 5;
80
+ if (lastRank > 2)
81
+ return 2;
82
+ return 0;
83
+ }
84
+ else {
85
+ if (lastRank === null)
86
+ return 0;
87
+ if (lastRank < 2)
88
+ return 2;
89
+ if (lastRank < 5)
90
+ return 5;
91
+ return 8;
92
+ }
93
+ };
94
+ const ranks = [];
95
+ let lastAssignedRank = null;
96
+ for (let i = 1; i < parts.length; i++) {
97
+ const token = parts[i];
98
+ if (!token)
99
+ continue;
100
+ const prefix = token.charAt(0);
101
+ const value = token.slice(1);
102
+ if (calendar === DefaultCalendars.UNIX && prefix === "s") {
103
+ comp.unixSeconds = parseFloat(value);
104
+ ranks.push(9);
105
+ continue;
106
+ }
107
+ if (prefix === "m") {
108
+ const rank = assignMRank(lastAssignedRank, initialOrder);
109
+ switch (rank) {
110
+ case 8:
111
+ comp.millennium = parseInt(value, 10);
112
+ break;
113
+ case 5:
114
+ comp.month = parseInt(value, 10);
115
+ break;
116
+ case 2:
117
+ comp.minute = parseInt(value, 10);
118
+ break;
119
+ case 0:
120
+ comp.millisecond = parseInt(value, 10);
121
+ break;
122
+ }
123
+ ranks.push(rank);
124
+ lastAssignedRank = rank;
125
+ }
126
+ else {
127
+ const rank = fixedRankMap[prefix];
128
+ if (rank !== undefined) {
129
+ switch (prefix) {
130
+ case "c":
131
+ comp.century = parseInt(value, 10);
132
+ break;
133
+ case "y":
134
+ comp.year = parseInt(value, 10);
135
+ break;
136
+ case "d":
137
+ comp.day = parseInt(value, 10);
138
+ break;
139
+ case "h":
140
+ comp.hour = parseInt(value, 10);
141
+ break;
142
+ case "s":
143
+ comp.second = parseFloat(value);
144
+ break;
145
+ }
146
+ ranks.push(rank);
147
+ lastAssignedRank = rank;
148
+ }
149
+ }
150
+ }
151
+ let order = TimeOrder.DESC;
152
+ if (ranks.length > 1) {
153
+ const isAsc = ranks.every((v, i, a) => i === 0 || a[i - 1] <= v);
154
+ const isDesc = ranks.every((v, i, a) => i === 0 || a[i - 1] >= v);
155
+ if (isAsc && !isDesc)
156
+ order = TimeOrder.ASC;
157
+ }
158
+ return { components: comp, order };
159
+ }
160
+ //# sourceMappingURL=tps-string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tps-string.js","sourceRoot":"","sources":["../../../src/utils/tps-string.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,SAAS,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEtE;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAmB;IAC/C,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACrD,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,0BAA0B,IAAI,CAAC,QAAQ,uDAAuD,CAC/F,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;IAC3B,IAAI,QAAQ,KAAK,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnC,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAgD;QAC1D,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACzB,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACtB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACnB,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACpB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAClB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACnB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrB,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;KAC3B,CAAC;IAEF,MAAM,KAAK,GAAc,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,IAAI,CAAC;IACtD,MAAM,YAAY,GAAG,KAAK,KAAK,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAE9E,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,YAAY,EAAE,CAAC;QACvC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,IAAI,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAa;IAEb,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAA2B,EAAE,QAAQ,EAAE,CAAC;IAElD,MAAM,YAAY,GAA2B;QAC3C,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;KACL,CAAC;IAEF,IAAI,YAAY,GAAc,SAAS,CAAC,IAAI,CAAC;IAC7C,IAAI,QAAQ,KAAK,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;YAC/B,IAAI,EAAE,IAAI,EAAE,IAAI,YAAY;gBAAE,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YACrE,IAAI,KAAK;gBAAE,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,CAAC,QAAuB,EAAE,GAAc,EAAU,EAAE;QACtE,IAAI,GAAG,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,CAAC,CAAC;YAChC,IAAI,QAAQ,GAAG,CAAC;gBAAE,OAAO,CAAC,CAAC;YAC3B,IAAI,QAAQ,GAAG,CAAC;gBAAE,OAAO,CAAC,CAAC;YAC3B,OAAO,CAAC,CAAC;QACX,CAAC;aAAM,CAAC;YACN,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,CAAC,CAAC;YAChC,IAAI,QAAQ,GAAG,CAAC;gBAAE,OAAO,CAAC,CAAC;YAC3B,IAAI,QAAQ,GAAG,CAAC;gBAAE,OAAO,CAAC,CAAC;YAC3B,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAE3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAE7B,IAAI,QAAQ,KAAK,gBAAgB,CAAC,IAAI,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACzD,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACd,SAAS;QACX,CAAC;QAED,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,WAAW,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;YACzD,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,CAAC;oBACJ,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACtC,MAAM;gBACR,KAAK,CAAC;oBACJ,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACjC,MAAM;gBACR,KAAK,CAAC;oBACJ,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAClC,MAAM;gBACR,KAAK,CAAC;oBACJ,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBACvC,MAAM;YACV,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,gBAAgB,GAAG,IAAI,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,QAAQ,MAAM,EAAE,CAAC;oBACf,KAAK,GAAG;wBACN,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBACnC,MAAM;oBACR,KAAK,GAAG;wBACN,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBAChC,MAAM;oBACR,KAAK,GAAG;wBACN,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBAC/B,MAAM;oBACR,KAAK,GAAG;wBACN,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;wBAChC,MAAM;oBACR,KAAK,GAAG;wBACN,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;wBAChC,MAAM;gBACV,CAAC;gBACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,gBAAgB,GAAG,IAAI,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAAc,SAAS,CAAC,IAAI,CAAC;IACtC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAClE,IAAI,KAAK,IAAI,CAAC,MAAM;YAAE,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC;IAC9C,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,10 +2,18 @@
2
2
  * TPS: Temporal Positioning System
3
3
  * The Universal Protocol for Space-Time Coordinates.
4
4
  * @packageDocumentation
5
- * @version 0.5.34
5
+ * @version 0.6.0
6
6
  * @license Apache-2.0
7
7
  * @copyright 2026 TPS Standards Working Group
8
8
  *
9
+ * v0.5.35 Changes:
10
+ * - Added TPS.now(), TPS.diff(), TPS.add() convenience methods
11
+ * - Added Chinese Lunisolar (chin) calendar driver
12
+ * - Added DriverManager (driver registry separated from TPS class)
13
+ * - Added timezone utility (src/utils/timezone.ts) with IANA + offset support
14
+ * - TPS.toDate() now respects ;tz= extensions when present
15
+ * - ESM dual-mode exports + browser IIFE bundle
16
+ *
9
17
  * v0.5.0 Changes:
10
18
  * - Added Actor anchor (A:) for provenance tracking
11
19
  * - Added Signature (!) for cryptographic verification
@@ -16,9 +24,13 @@ export * from "./types";
16
24
  export * from "./uid";
17
25
  export * from "./date";
18
26
  export { Env } from "./utils/env";
27
+ export { DriverManager } from "./driver-manager";
28
+ export { utcToLocal, localToUtc, getOffsetString } from "./utils/timezone";
29
+ import { DriverManager } from "./driver-manager";
19
30
  import { CalendarDriver, TPSComponents, TimeOrder } from "./types";
20
31
  export declare class TPS {
21
- private static readonly drivers;
32
+ /** Shared DriverManager instance — use TPS.driverManager for direct access. */
33
+ static readonly driverManager: DriverManager;
22
34
  /**
23
35
  * Registers a calendar driver plugin.
24
36
  * @param driver - The driver instance to register.
@@ -144,7 +156,84 @@ export declare class TPS {
144
156
  * ```
145
157
  */
146
158
  static formatCalendarDate(calendar: string, components: Partial<TPSComponents>, format?: string): string;
159
+ /**
160
+ * Returns a TPS time string for the current moment.
161
+ * Shorthand for `TPS.fromDate(new Date(), calendar, opts)`.
162
+ *
163
+ * @param calendar - Calendar code. Defaults to 'greg'.
164
+ * @param opts - Optional `order` (ASC/DESC) parameter.
165
+ * @returns TPS time string.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * TPS.now(); // "T:greg.m3.c1.y26.m3.d4.h06.m30.s00.m0"
170
+ * TPS.now('hij'); // "T:hij.y1447.m09.d05.h06.m30.s00"
171
+ * ```
172
+ */
173
+ static now(calendar?: string, opts?: {
174
+ order?: TimeOrder;
175
+ }): string;
176
+ /**
177
+ * Returns the difference in milliseconds between two TPS strings.
178
+ * The result is `t2 - t1`; negative if t1 is after t2.
179
+ *
180
+ * @param t1 - First TPS string (subtracted from t2).
181
+ * @param t2 - Second TPS string.
182
+ * @returns Milliseconds between the two moments, or NaN on parse failure.
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * const ms = TPS.diff('T:greg.m3.c1.y26.m1.d1.h0.m0.s0.m0',
187
+ * 'T:greg.m3.c1.y26.m1.d2.h0.m0.s0.m0');
188
+ * // 86_400_000 (one day)
189
+ * ```
190
+ */
191
+ static diff(t1: string, t2: string): number;
192
+ /**
193
+ * Returns a new TPS string shifted by the given duration.
194
+ * The result is in the same calendar as the original string.
195
+ *
196
+ * @param tpsStr - Source TPS string.
197
+ * @param duration - Object with optional `days`, `hours`, `minutes`, `seconds`, `milliseconds`.
198
+ * @returns Shifted TPS string, or null if the input is invalid.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * const t = 'T:greg.m3.c1.y26.m1.d9.h14.m30.s25.m0';
203
+ * TPS.add(t, { days: 7 }); // one week later
204
+ * TPS.add(t, { hours: -2 }); // two hours earlier
205
+ * ```
206
+ */
207
+ static add(tpsStr: string, duration: {
208
+ days?: number;
209
+ hours?: number;
210
+ minutes?: number;
211
+ seconds?: number;
212
+ milliseconds?: number;
213
+ }): string | null;
147
214
  private static _mapGroupsToComponents;
215
+ /**
216
+ * Parses a multi-layer location string (before @T:) into component fields.
217
+ * Layers are `;`-separated. Each layer is identified by its prefix token.
218
+ *
219
+ * Supported layers:
220
+ * L:lat,lon[,altm] — GPS
221
+ * L:~|L:-|L:redacted — Privacy markers
222
+ * P:cc=JO,ci=AMM,... — Place (country/city codes and names)
223
+ * S2:token — S2 cell
224
+ * H3:token — H3 cell
225
+ * 3W:word.word.word — What3Words
226
+ * plus:token — Plus Code
227
+ * net:ip4:x.x.x.x — IPv4
228
+ * net:ip6:x::x — IPv6
229
+ * node:name — Logical node/host
230
+ * bldg:name — Building
231
+ * floor:x — Floor
232
+ * room:x — Room
233
+ * door:x — Door
234
+ * zone:x — Zone
235
+ */
236
+ private static _parseLocationLayers;
148
237
  }
149
238
  /**
150
239
  * `TpsDate` is a Date-like wrapper with native TPS conversion helpers.