@powfix/core-js 0.9.22

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 (101) hide show
  1. package/browser.ts +73 -0
  2. package/dist/browser.d.ts +32 -0
  3. package/dist/browser.js +58 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +20 -0
  6. package/dist/src/constants/COORDINATE.d.ts +7 -0
  7. package/dist/src/constants/COORDINATE.js +10 -0
  8. package/dist/src/constants/DISTANCE.d.ts +13 -0
  9. package/dist/src/constants/DISTANCE.js +18 -0
  10. package/dist/src/constants/DURATION.d.ts +16 -0
  11. package/dist/src/constants/DURATION.js +21 -0
  12. package/dist/src/interfaces/Coordinate.d.ts +8 -0
  13. package/dist/src/interfaces/Coordinate.js +2 -0
  14. package/dist/src/interfaces/Point2.d.ts +4 -0
  15. package/dist/src/interfaces/Point2.js +2 -0
  16. package/dist/src/interfaces/Point3.d.ts +4 -0
  17. package/dist/src/interfaces/Point3.js +2 -0
  18. package/dist/src/scripts/base64-polyfill.d.ts +1 -0
  19. package/dist/src/scripts/base64-polyfill.js +14 -0
  20. package/dist/src/services/Session.d.ts +27 -0
  21. package/dist/src/services/Session.js +140 -0
  22. package/dist/src/services/browser.d.ts +2 -0
  23. package/dist/src/services/browser.js +20 -0
  24. package/dist/src/services/index.d.ts +2 -0
  25. package/dist/src/services/index.js +19 -0
  26. package/dist/src/services/redis/RedisClient.d.ts +20 -0
  27. package/dist/src/services/redis/RedisClient.js +70 -0
  28. package/dist/src/services/redis/RedisPublisher.d.ts +13 -0
  29. package/dist/src/services/redis/RedisPublisher.js +61 -0
  30. package/dist/src/services/redis/RedisSubscriber.d.ts +11 -0
  31. package/dist/src/services/redis/RedisSubscriber.js +68 -0
  32. package/dist/src/services/redis/index.d.ts +3 -0
  33. package/dist/src/services/redis/index.js +20 -0
  34. package/dist/src/services/time/TimeService.d.ts +64 -0
  35. package/dist/src/services/time/TimeService.js +235 -0
  36. package/dist/src/services/time/index.d.ts +1 -0
  37. package/dist/src/services/time/index.js +17 -0
  38. package/dist/src/types/IntRage.d.ts +3 -0
  39. package/dist/src/types/IntRage.js +2 -0
  40. package/dist/src/utils/ArrayUtils.d.ts +10 -0
  41. package/dist/src/utils/ArrayUtils.js +20 -0
  42. package/dist/src/utils/BooleanUtils.d.ts +1 -0
  43. package/dist/src/utils/BooleanUtils.js +9 -0
  44. package/dist/src/utils/CoordinateUtils.d.ts +8 -0
  45. package/dist/src/utils/CoordinateUtils.js +42 -0
  46. package/dist/src/utils/DateUtils.d.ts +12 -0
  47. package/dist/src/utils/DateUtils.js +212 -0
  48. package/dist/src/utils/JuminNumberUtils.d.ts +4 -0
  49. package/dist/src/utils/JuminNumberUtils.js +50 -0
  50. package/dist/src/utils/NumberUtils.d.ts +4 -0
  51. package/dist/src/utils/NumberUtils.js +25 -0
  52. package/dist/src/utils/Point3Utils.d.ts +4 -0
  53. package/dist/src/utils/Point3Utils.js +12 -0
  54. package/dist/src/utils/RandomUtils.d.ts +8 -0
  55. package/dist/src/utils/RandomUtils.js +64 -0
  56. package/dist/src/utils/Sequencer.d.ts +39 -0
  57. package/dist/src/utils/Sequencer.js +148 -0
  58. package/dist/src/utils/StringUtils.d.ts +5 -0
  59. package/dist/src/utils/StringUtils.js +37 -0
  60. package/dist/src/utils/UuidUtils.d.ts +14 -0
  61. package/dist/src/utils/UuidUtils.js +49 -0
  62. package/dist/src/utils/Validator.d.ts +48 -0
  63. package/dist/src/utils/Validator.js +118 -0
  64. package/dist/src/utils/global/between.d.ts +1 -0
  65. package/dist/src/utils/global/between.js +7 -0
  66. package/dist/src/utils/global/sleep.d.ts +1 -0
  67. package/dist/src/utils/global/sleep.js +21 -0
  68. package/index.ts +5 -0
  69. package/package.json +42 -0
  70. package/src/constants/COORDINATE.ts +9 -0
  71. package/src/constants/DISTANCE.ts +15 -0
  72. package/src/constants/DURATION.ts +18 -0
  73. package/src/interfaces/Coordinate.ts +9 -0
  74. package/src/interfaces/Point2.ts +4 -0
  75. package/src/interfaces/Point3.ts +5 -0
  76. package/src/scripts/base64-polyfill.ts +13 -0
  77. package/src/services/Session.ts +141 -0
  78. package/src/services/browser.ts +5 -0
  79. package/src/services/index.ts +4 -0
  80. package/src/services/redis/RedisClient.ts +79 -0
  81. package/src/services/redis/RedisPublisher.ts +48 -0
  82. package/src/services/redis/RedisSubscriber.ts +49 -0
  83. package/src/services/redis/index.ts +4 -0
  84. package/src/services/time/TimeService.ts +304 -0
  85. package/src/services/time/index.ts +1 -0
  86. package/src/types/IntRage.ts +5 -0
  87. package/src/utils/ArrayUtils.ts +25 -0
  88. package/src/utils/BooleanUtils.ts +4 -0
  89. package/src/utils/CoordinateUtils.ts +50 -0
  90. package/src/utils/DateUtils.ts +213 -0
  91. package/src/utils/JuminNumberUtils.ts +47 -0
  92. package/src/utils/NumberUtils.ts +23 -0
  93. package/src/utils/Point3Utils.ts +11 -0
  94. package/src/utils/RandomUtils.ts +62 -0
  95. package/src/utils/Sequencer.ts +178 -0
  96. package/src/utils/StringUtils.ts +43 -0
  97. package/src/utils/UuidUtils.ts +46 -0
  98. package/src/utils/Validator.ts +162 -0
  99. package/src/utils/global/between.ts +3 -0
  100. package/src/utils/global/sleep.ts +6 -0
  101. package/tsconfig.json +103 -0
@@ -0,0 +1,49 @@
1
+ import {RedisClient} from "./RedisClient";
2
+ import {PubSubListener} from "@redis/client/dist/lib/client/pub-sub";
3
+
4
+ export class RedisSubscriber extends RedisClient {
5
+ public constructor(options?: RedisClient.RedisClientOptions) {
6
+ super(options);
7
+ console.log(Date.now(), 'Subscriber', 'initialized');
8
+ }
9
+
10
+ public subscribe = async <T extends boolean = false>(channels: string | string[], listener: PubSubListener<T>, bufferMode?: T | undefined) => {
11
+ for (const channel of Array.isArray(channels) ? channels : [channels]) {
12
+ if ((/\*/g).test(channel)) {
13
+ await this.client.pSubscribe(channel, listener, bufferMode);
14
+ } else {
15
+ await this.client.subscribe(channel, listener, bufferMode);
16
+ }
17
+ }
18
+ };
19
+
20
+ public unsubscribe = async <T extends boolean = false>(channels: string | string[], listener?: PubSubListener<T> | undefined, bufferMode?: T | undefined): Promise<void> => {
21
+ for (const channel of Array.isArray(channels) ? channels : [channels]) {
22
+ if ((/\*/g).test(channel)) {
23
+ await this.client.pUnsubscribe(channel, listener, bufferMode);
24
+ } else {
25
+ await this.client.unsubscribe(channel, listener, bufferMode);
26
+ }
27
+ }
28
+ };
29
+
30
+ public async start(): Promise<RedisClient.Status> {
31
+ const status = await super.start();
32
+ await this.registerListeners();
33
+ return status;
34
+ }
35
+
36
+ public async stop(): Promise<RedisClient.Status> {
37
+ const status = await super.stop();
38
+ await this.unregisterListeners();
39
+ return status;
40
+ }
41
+
42
+ protected async registerListeners() {
43
+
44
+ }
45
+
46
+ protected async unregisterListeners() {
47
+
48
+ }
49
+ }
@@ -0,0 +1,4 @@
1
+ // Files
2
+ export * from './RedisClient';
3
+ export * from './RedisPublisher';
4
+ export * from './RedisSubscriber';
@@ -0,0 +1,304 @@
1
+ import EventEmitter from "events";
2
+
3
+ const LOG_TAG: string = 'TimeService';
4
+
5
+ export class TimeService {
6
+ protected status: TimeService.Status = TimeService.Status.STOPPED;
7
+ private offset?: TimeService.Offset | undefined;
8
+ private option: TimeService.Option;
9
+ private syncedAt?: TimeService.TimeStamp | undefined;
10
+
11
+ // Emitter
12
+ private emitter = new EventEmitter({});
13
+ public readonly on = this.emitter.on;
14
+ public readonly off = this.emitter.off;
15
+ private readonly emit = this.emitter.emit;
16
+
17
+ public static calculateNTPResultOffset(ntpResult: TimeService.NTPResult): TimeService.Offset {
18
+ const {t1, t2, t3, t4} = ntpResult;
19
+ return ((t2 - t1) + (t3 - t4)) / 2;
20
+ }
21
+
22
+ constructor(option: TimeService.Option) {
23
+ this.option = option;
24
+
25
+ if (option.autoStart) {
26
+ this.start();
27
+ }
28
+
29
+ // Binding
30
+ this.start = this.start.bind(this);
31
+ this.stop = this.stop.bind(this);
32
+ this.sync = this.sync.bind(this);
33
+ this.getOption = this.getOption.bind(this);
34
+ this.setOption = this.setOption.bind(this);
35
+ }
36
+
37
+ public getOption(): TimeService.Option {
38
+ return this.option;
39
+ }
40
+
41
+ public setOption(option: TimeService.Option): TimeService.Option {
42
+ return this.option = option;
43
+ }
44
+
45
+ public getOffset(defaultValue: TimeService.Offset): TimeService.Offset;
46
+ public getOffset(): TimeService.Offset | undefined;
47
+ public getOffset(defaultValue?: TimeService.Offset): TimeService.Offset | undefined {
48
+ if (this.offset !== undefined) {
49
+ return this.offset;
50
+ }
51
+ if (defaultValue !== undefined) {
52
+ return defaultValue;
53
+ }
54
+ return undefined;
55
+ }
56
+
57
+ public setOffset(offset: TimeService.Offset): TimeService.Offset
58
+ public setOffset(offset: TimeService.Offset | undefined): TimeService.Offset
59
+ public setOffset(offset?: TimeService.Offset): TimeService.Offset | undefined {
60
+ return this.offset = offset;
61
+ }
62
+
63
+ public getSyncedAt(): TimeService.TimeStamp | undefined {
64
+ return this.syncedAt;
65
+ }
66
+
67
+ private setSyncedAt(syncedAt: TimeService.TimeStamp | undefined): TimeService.TimeStamp | undefined {
68
+ this.syncedAt = syncedAt;
69
+
70
+ // Emit
71
+ this.emit(TimeService.EVENT.SYNCED, syncedAt);
72
+
73
+ return syncedAt;
74
+ }
75
+
76
+ public getSyncInterval(): number | null {
77
+ if (this.option.syncInterval === undefined) {
78
+ // If option is undefined using default value
79
+ return TimeService.DEFAULT_SYNC_INTERVAL;
80
+ }
81
+
82
+ if (this.option.syncInterval === null || this.option.syncInterval === -1) {
83
+ // If option is null, do not sync automatically
84
+ return null;
85
+ }
86
+
87
+ return this.option.syncInterval;
88
+ }
89
+
90
+ public setSyncInterval(interval: TimeService.Option['syncInterval']) {
91
+ this.option.syncInterval = interval;
92
+
93
+ // Emit
94
+ this.emit(TimeService.EVENT.SYNC_INTERVAL_CHANGED, interval);
95
+
96
+ if (this.status === TimeService.Status.RUNNING) {
97
+ if (this.syncHandler !== undefined) {
98
+ this.stopSync();
99
+ this.startSync();
100
+ }
101
+ }
102
+ }
103
+
104
+ public getClientTime(defaultValue: TimeService.TimeStamp = Date.now()): TimeService.TimeStamp {
105
+ try {
106
+ if (typeof this.option.clientTimeProvider === 'function') {
107
+ return this.option.clientTimeProvider();
108
+ }
109
+ } catch (e) {
110
+ console.error(e);
111
+ }
112
+ return defaultValue;
113
+ }
114
+
115
+ public getServerTime(): TimeService.TimeStamp | null {
116
+ const offset = this.getOffset();
117
+ if (offset === undefined) {
118
+ return null;
119
+ }
120
+
121
+ const clientTime = this.getClientTime();
122
+ return clientTime + offset;
123
+ }
124
+
125
+ public getTime(): number {
126
+ return this.getServerTime() || this.getClientTime();
127
+ }
128
+
129
+ private readonly fetchServerNTPResult = async (t1: TimeService.NTPResult['t1']): Promise<TimeService.ServerNTPResult | null> => {
130
+ try {
131
+ if (typeof this.option.serverTimeProvider === 'function') {
132
+ return await this.option.serverTimeProvider(t1);
133
+ }
134
+ } catch (e) {
135
+ console.error(e);
136
+ }
137
+ return null;
138
+ }
139
+
140
+ public getStatus(): TimeService.Status {
141
+ return this.status;
142
+ }
143
+
144
+ public start() {
145
+ if (this.status !== TimeService.Status.STOPPED) {
146
+ console.warn(LOG_TAG, 'service is not stopped');
147
+ return;
148
+ }
149
+
150
+ // Change status
151
+ this.status = TimeService.Status.RUNNING;
152
+
153
+ // Sync immediately
154
+ this.sync().finally(() => {});
155
+
156
+ // Start sync
157
+ this.startSync();
158
+ }
159
+
160
+ public stop() {
161
+ if (this.status !== TimeService.Status.RUNNING) {
162
+ console.warn(LOG_TAG, 'service is not running');
163
+ return;
164
+ }
165
+
166
+ // Change status
167
+ this.status = TimeService.Status.RUNNING;
168
+
169
+ // Stop sync
170
+ this.stopSync();
171
+
172
+ // Reset offset
173
+ this.setOffset(undefined);
174
+
175
+ // Reset synced at
176
+ this.setSyncedAt(undefined);
177
+ }
178
+
179
+ public async sync(): Promise<TimeService.Offset | null> {
180
+ try {
181
+ // T1 (Client Request Time)
182
+ const requestedAt: number = Date.now();
183
+
184
+ // Fetch server time from server
185
+ const serverNtpResult = await this.fetchServerNTPResult(requestedAt);
186
+
187
+ // Check is null
188
+ if (serverNtpResult === null) {
189
+ console.warn(LOG_TAG, 'Failed to get server time');
190
+ return null;
191
+ }
192
+
193
+ // T2 (Server Receive Time)
194
+ const {t2} = serverNtpResult;
195
+
196
+ // Check is not a number
197
+ if (isNaN(Number(t2))) {
198
+ // Not a Number
199
+ console.error(LOG_TAG, 'invalid server time(t2), not a number', t2);
200
+ return null;
201
+ }
202
+
203
+ // T3 (Server Transmit Time)
204
+ const {t3} = serverNtpResult;
205
+
206
+ // Check is not a number
207
+ if (isNaN(Number(t3))) {
208
+ // Not a Number
209
+ console.error(LOG_TAG, 'invalid server time(t2), not a number', t2);
210
+ return null;
211
+ }
212
+
213
+ // T4 (Client Receive Time)
214
+ const receivedAt: number = Date.now();
215
+
216
+ const ntpResult: TimeService.NTPResult = {
217
+ t1: requestedAt,
218
+ t2: t2,
219
+ t3: t3,
220
+ t4: receivedAt,
221
+ };
222
+
223
+ // Calculate offset
224
+ const offset = TimeService.calculateNTPResultOffset(ntpResult);
225
+
226
+ // Save calculated offset
227
+ this.setOffset(offset);
228
+
229
+ // Mark synced timestamp
230
+ this.setSyncedAt(Date.now());
231
+ } catch (e) {
232
+ console.error(e);
233
+ }
234
+
235
+ return null;
236
+ }
237
+
238
+ private syncHandler?: ReturnType<typeof setInterval> | undefined;
239
+ private startSync() {
240
+ if (this.syncHandler !== undefined) {
241
+ console.warn('sync handler is not undefined', this.syncHandler);
242
+ return;
243
+ }
244
+
245
+ const syncInterval = this.getSyncInterval();
246
+ if (syncInterval === null) {
247
+ return;
248
+ }
249
+
250
+ this.syncHandler = setInterval(this.sync, syncInterval);
251
+ };
252
+
253
+ private stopSync() {
254
+ if (this.syncHandler === undefined) {
255
+ return;
256
+ }
257
+ clearInterval(this.syncHandler);
258
+ this.syncHandler = undefined;
259
+ };
260
+ }
261
+
262
+ export namespace TimeService {
263
+ export const DEFAULT_SYNC_INTERVAL: number = 60000;
264
+
265
+ export enum Status {
266
+ STOPPED = 0,
267
+ RUNNING = 1,
268
+ }
269
+
270
+ export type Offset = number;
271
+ export type TimeStamp = number;
272
+
273
+ export interface NTPResult {
274
+ // T1 (Client Request Time)
275
+ t1: TimeStamp;
276
+
277
+ // T2 (Server Receive Time)
278
+ t2: TimeStamp;
279
+
280
+ // T3 (Server Transmit Time)
281
+ t3: TimeStamp;
282
+
283
+ // T4 (Client Receive Time)
284
+ t4: TimeStamp;
285
+ }
286
+
287
+ export interface ServerNTPResult extends Pick<NTPResult, 't2' | 't3'> {}
288
+
289
+ export type ClientTimeProvider = () => TimeStamp;
290
+ // export type ServerTimeProvider = ((t1: NTPResult['t1']) => ServerNTPResult) | ((t1: NTPResult['t1']) => Promise<ServerNTPResult>);
291
+ export type ServerTimeProvider = (t1: NTPResult['t1']) => (ServerNTPResult | null) | (Promise<ServerNTPResult | null>);
292
+
293
+ export interface Option {
294
+ autoStart?: boolean;
295
+ syncInterval?: number | null | undefined; // Sync interval in milliseconds
296
+ clientTimeProvider?: ClientTimeProvider | undefined;
297
+ serverTimeProvider?: ServerTimeProvider | undefined;
298
+ }
299
+
300
+ export enum EVENT {
301
+ SYNCED = 'SYNCED',
302
+ SYNC_INTERVAL_CHANGED = 'SYNC_INTERVAL_CHANGED',
303
+ }
304
+ }
@@ -0,0 +1 @@
1
+ export * from "./TimeService";
@@ -0,0 +1,5 @@
1
+ type Enumerate<N extends number, Acc extends number[] = []> = Acc['length'] extends N
2
+ ? Acc[number]
3
+ : Enumerate<N, [...Acc, Acc['length']]>
4
+
5
+ export type IntRange<F extends number, T extends number> = Exclude<Enumerate<T>, Enumerate<F>> | T;
@@ -0,0 +1,25 @@
1
+ export class ArrayUtils {
2
+
3
+ /**
4
+ * 객체를 요소로 가지는 배열에서 가장 큰 값(Property)를 가지는 객체를 반환한다
5
+ * @param e 객체 배열
6
+ * @param key 값을 비교할 Property 키
7
+ */
8
+ static getGreatestObject(e: any[], key: string) {
9
+ return e.reduce((prev, current) => (
10
+ (prev[key] > current[key] ? prev : current)
11
+ ));
12
+ }
13
+
14
+ static removeDuplicate<T>(arr: T[]): T[] {
15
+ return [...new Set(arr)]
16
+ }
17
+
18
+ static removeObjectDuplicate(arr: any[], key: string) {
19
+ return arr.filter((v, i, self) => (
20
+ i === self.findIndex(e => (
21
+ e[key] === v[key]
22
+ ))
23
+ ))
24
+ }
25
+ }
@@ -0,0 +1,4 @@
1
+ export function parseBoolean(value: any, defaultValue: boolean): boolean {
2
+ if (value === undefined || value === null) return defaultValue;
3
+ return (value === 'true' || value === true) || (value === 1 || value === '1');
4
+ }
@@ -0,0 +1,50 @@
1
+ import {Coordinate} from "../interfaces/Coordinate";
2
+
3
+ export class CoordinateUtils {
4
+ public static isValidLatitude(latitude: Coordinate['latitude'] | string) {
5
+ return /^-?([0-8]?[0-9]|90)(\.[0-9]{1,15})$/.test(latitude.toString());
6
+ }
7
+
8
+ public static isValidLongitude(longitude: Coordinate['longitude'] | string) {
9
+ return /^-?([0-9]{1,2}|1[0-7][0-9]|180)(\.[0-9]{1,14})$/.test(longitude.toString());
10
+ }
11
+
12
+ public static isValidLatitudeLongitude(latitude: Coordinate['latitude'] | string, longitude: Coordinate['longitude'] | string) {
13
+ return CoordinateUtils.isValidLatitude(latitude) && CoordinateUtils.isValidLongitude(longitude);
14
+ }
15
+
16
+ public static isValidCoordinate(coordinate: Coordinate): boolean {
17
+ return this.isValidLatitudeLongitude(coordinate.latitude, coordinate.longitude);
18
+ }
19
+
20
+ public static crowDistance(...coordinates: Coordinate[]): number {
21
+ if (coordinates.length <= 2) {
22
+ const toRad = (value: number) => value * Math.PI / 180;
23
+
24
+ const c1 = coordinates[0];
25
+ const c2 = coordinates[1];
26
+ if (!c1 || !c2) {
27
+ return 0;
28
+ }
29
+
30
+ const R = 6371e3;
31
+ const dLat = toRad(c2.latitude - c1.latitude);
32
+ const dLon = toRad(c2.longitude - c1.longitude);
33
+ const lat1 = toRad(c1.latitude);
34
+ const lat2 = toRad(c2.latitude);
35
+
36
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
37
+ Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
38
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
39
+
40
+ return R * c;
41
+ }
42
+
43
+ let totalDistance: number = 0;
44
+ for (let i = 0; i < coordinates.length - 1; ++i) {
45
+ totalDistance += this.crowDistance(coordinates[i], coordinates[i + 1]);
46
+ }
47
+
48
+ return totalDistance;
49
+ }
50
+ }
@@ -0,0 +1,213 @@
1
+ import moment, {Moment, MomentInput, RelativeTimeSpec} from "moment";
2
+
3
+ export class DateUtils {
4
+ public static relativeDate = (input: MomentInput, from: MomentInput = Date.now()): string => {
5
+ // Create new moment instance to apply new locale
6
+ const datetime = moment.isMoment(input) ? moment(input.toDate()) : moment(input);
7
+
8
+ if (!datetime.isValid()) {
9
+ console.error('core-js:DateUtils.relativeDate() datetime is invalid', datetime);
10
+ return '<INVALID DATE>';
11
+ }
12
+
13
+ return datetime.from(from);
14
+ };
15
+
16
+ public static setLocale = (language: DateUtils.Locale) => {
17
+ const relativeTime = DateUtils.getRelativeTimeSpec(language);
18
+ if (relativeTime !== undefined) {
19
+ moment.updateLocale(language, {relativeTime});
20
+ }
21
+ moment.locale(language);
22
+ };
23
+
24
+ private static getRelativeTimeSpec = (locale: DateUtils.Locale): RelativeTimeSpec | undefined => {
25
+ if (locale in DateUtils.relativeTimeSpecs) {
26
+ return DateUtils.relativeTimeSpecs[locale];
27
+ }
28
+ return undefined;
29
+ };
30
+ }
31
+
32
+ export namespace DateUtils {
33
+ export type Locale = string;
34
+
35
+ export const relativeTimeSpecs: {[key: Locale]: RelativeTimeSpec} = {
36
+ ko: {
37
+ future: "%s 후",
38
+ past: "%s 전",
39
+ s: number => `${number}초`,
40
+ ss: number => `${number}초`,
41
+ m: number => `${number}분`,
42
+ mm: number => `${number}분`,
43
+ h: number => `${number}시간`,
44
+ hh: number => `${number}시간`,
45
+ d: number => `${number}일`,
46
+ dd: number => `${number}일`,
47
+ M: number => `${number}개월`,
48
+ MM: number => `${number}개월`,
49
+ y: number => `${number}년`,
50
+ yy: number => `${number}년`
51
+ } as RelativeTimeSpec,
52
+ en: {
53
+ future: "in %s",
54
+ past: "%s ago",
55
+ s: number => number === 1 ? `${number} second`: `${number} seconds`,
56
+ ss: number => `${number} seconds`,
57
+ m: number => number === 1 ? `${number} minute`: `${number} minutes`,
58
+ mm: number => `${number} minutes`,
59
+ h: number => number === 1 ? `${number} hour`: `${number} hours`,
60
+ hh: number => `${number} hours`,
61
+ d: number => number === 1 ? `${number} day`: `${number} days`,
62
+ dd: number => `${number} days`,
63
+ M: number => number === 1 ? `${number} month`: `${number} months`,
64
+ MM: number => `${number} months`,
65
+ y: number => number === 1 ? `${number} year`: `${number} years`,
66
+ yy: number => `${number} years`
67
+ } as RelativeTimeSpec,
68
+ ja: {
69
+ future: "%s後",
70
+ past: "%s前",
71
+ s: number => `${number}秒`,
72
+ ss: number => `${number}秒`,
73
+ m: number => `${number}分`,
74
+ mm: number => `${number}分`,
75
+ h: number => `${number}時`,
76
+ hh: number => `${number}時`,
77
+ d: number => `${number}日`,
78
+ dd: number => `${number}日`,
79
+ M: number => `${number}月`,
80
+ MM: number => `${number}月`,
81
+ y: number => `${number}年`,
82
+ yy: number => `${number}年`
83
+ } as RelativeTimeSpec,
84
+ zh: {
85
+ future: "%s后",
86
+ past: "%s前",
87
+ s: number => `${number}秒`,
88
+ ss: number => `${number}秒`,
89
+ m: number => `${number}分钟`,
90
+ mm: number => `${number}分钟`,
91
+ h: number => `${number}个小时`,
92
+ hh: number => `${number}个小时`,
93
+ d: number => `${number}天`,
94
+ dd: number => `${number}天`,
95
+ M: number => `${number}个月`,
96
+ MM: number => `${number}个月`,
97
+ y: number => `${number}年`,
98
+ yy: number => `${number}年`
99
+ } as RelativeTimeSpec,
100
+ ru: {
101
+ future: "через %s",
102
+ past: "%s назад",
103
+ s: number => `${number} секунд`,
104
+ ss: number => `${number} секунд`,
105
+ m: number => `${number} минута`,
106
+ mm: number => `${number} минут`,
107
+ h: number => `${number} час`,
108
+ hh: number => `${number} часов`,
109
+ d: number => `${number} день`,
110
+ dd: number => `${number} дней`,
111
+ M: number => `${number} месяц`,
112
+ MM: number => `${number} месяцев`,
113
+ y: number => `${number} год`,
114
+ yy: number => `${number} лет`
115
+ } as RelativeTimeSpec,
116
+ uz: {
117
+ future: "%sdan keyin",
118
+ past: "%s avval",
119
+ s: number => `${number} soniya`,
120
+ ss: number => `${number} soniya`,
121
+ m: number => `${number} daqiqa`,
122
+ mm: number => `${number} daqiqa`,
123
+ h: number => `${number} soat`,
124
+ hh: number => `${number} soat`,
125
+ d: number => `${number} kun`,
126
+ dd: number => `${number} kun`,
127
+ M: number => `${number} oy`,
128
+ MM: number => `${number} oy`,
129
+ y: number => `${number} yil`,
130
+ yy: number => `${number} yil`
131
+ } as RelativeTimeSpec,
132
+ de: {
133
+ future: "in %s",
134
+ past: "vor %s",
135
+ s: number => `${number === 1 ? "einer" : number} Sekunde${number === 1 ? "" : "n"}`,
136
+ ss: number => `${number} Sekunde${number === 1 ? "" : "n"}`,
137
+ m: number => `${number === 1 ? "einer" : number} Minute${number === 1 ? "" : "n"}`,
138
+ mm: number => `${number} Minute${number === 1 ? "" : "n"}`,
139
+ h: number => `${number === 1 ? "einer" : number} Stunde${number === 1 ? "" : "n"}`,
140
+ hh: number => `${number} Stunde${number === 1 ? "" : "n"}`,
141
+ d: number => `${number === 1 ? "einem" : number} Tag${number === 1 ? "" : "en"}`,
142
+ dd: number => `${number} Tag${number === 1 ? "" : "en"}`,
143
+ M: number => `${number === 1 ? "einem" : number} Monat${number === 1 ? "" : "en"}`,
144
+ MM: number => `${number} Monat${number === 1 ? "" : "en"}`,
145
+ y: number => `${number === 1 ? "einem" : number} Jahr${number === 1 ? "" : "en"}`,
146
+ yy: number => `${number} Jahr${number === 1 ? "" : "en"}`
147
+ } as RelativeTimeSpec,
148
+ fr: {
149
+ future: "dans %s",
150
+ past: "il y a %s",
151
+ s: number => `quelques secondes`,
152
+ ss: number => `${number} secondes`,
153
+ m: number => `une minute`,
154
+ mm: number => `${number} minutes`,
155
+ h: number => `une heure`,
156
+ hh: number => `${number} heures`,
157
+ d: number => `un jour`,
158
+ dd: number => `${number} jours`,
159
+ M: number => `un mois`,
160
+ MM: number => `${number} mois`,
161
+ y: number => `un an`,
162
+ yy: number => `${number} ans`
163
+ } as RelativeTimeSpec,
164
+ vi: {
165
+ future: "sau %s",
166
+ past: "%s trước",
167
+ s: number => `${number} giây`,
168
+ ss: number => `${number} giây`,
169
+ m: number => `${number} phút`,
170
+ mm: number => `${number} phút`,
171
+ h: number => `${number} giờ`,
172
+ hh: number => `${number} giờ`,
173
+ d: number => `${number} ngày`,
174
+ dd: number => `${number} ngày`,
175
+ M: number => `${number} tháng`,
176
+ MM: number => `${number} tháng`,
177
+ y: number => `${number} năm`,
178
+ yy: number => `${number} năm`
179
+ } as RelativeTimeSpec,
180
+ th: {
181
+ future: "ใน %s",
182
+ past: "%s ที่แล้ว",
183
+ s: number => `${number} วินาที`,
184
+ ss: number => `${number} วินาที`,
185
+ m: number => `${number} นาที`,
186
+ mm: number => `${number} นาที`,
187
+ h: number => `${number} ชั่วโมง`,
188
+ hh: number => `${number} ชั่วโมง`,
189
+ d: number => `${number} วัน`,
190
+ dd: number => `${number} วัน`,
191
+ M: number => `${number} เดือน`,
192
+ MM: number => `${number} เดือน`,
193
+ y: number => `${number} ปี`,
194
+ yy: number => `${number} ปี`
195
+ } as RelativeTimeSpec,
196
+ fil: {
197
+ future: "sa loob ng %s",
198
+ past: "%s ang nakalipas",
199
+ s: number => `${number} segundo`,
200
+ ss: number => `${number} segundo`,
201
+ m: number => `${number} minuto`,
202
+ mm: number => `${number} minuto`,
203
+ h: number => `${number} oras`,
204
+ hh: number => `${number} oras`,
205
+ d: number => `${number} araw`,
206
+ dd: number => `${number} araw`,
207
+ M: number => `${number} buwan`,
208
+ MM: number => `${number} buwan`,
209
+ y: number => `${number} taon`,
210
+ yy: number => `${number} taon`
211
+ } as RelativeTimeSpec,
212
+ };
213
+ }