@prairielearn/formatter 1.3.14 → 1.4.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/dist/date.test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { assert, describe, it } from 'vitest';
2
- import { formatDate, formatDateYMD, formatDateYMDHM } from './date.js';
2
+ import { formatDate, formatDateFriendly, formatDateRangeFriendly, formatDateWithinRange, formatDateYMD, formatDateYMDHM, } from './date.js';
3
3
  describe('date formatting', () => {
4
4
  describe('formatDate', () => {
5
5
  it('formats a UTC date', () => {
@@ -67,5 +67,242 @@ describe('date formatting', () => {
67
67
  assert.equal(formatDateYMDHM(date, 'UTC'), '2018-01-01 00:01');
68
68
  });
69
69
  });
70
+ describe('formatDateWithinRange()', () => {
71
+ it('should handle a date within the same day in UTC', () => {
72
+ const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));
73
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
74
+ const end = new Date(Date.UTC(2018, 0, 1, 12, 59, 59));
75
+ assert.equal(formatDateWithinRange(date, start, end, 'UTC'), '12:34');
76
+ });
77
+ it('should handle a date within the same day in CST', () => {
78
+ const date = new Date(Date.UTC(2018, 0, 1, 23, 8, 57));
79
+ const start = new Date(Date.UTC(2018, 0, 1, 21, 0, 0));
80
+ const end = new Date(Date.UTC(2018, 0, 2, 2, 14, 0));
81
+ assert.equal(formatDateWithinRange(date, start, end, 'America/Chicago'), '17:08');
82
+ });
83
+ it('should handle a date within the same year in UTC', () => {
84
+ const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));
85
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
86
+ const end = new Date(Date.UTC(2018, 0, 4, 12, 59, 59));
87
+ assert.equal(formatDateWithinRange(date, start, end, 'UTC'), 'Jan 1, 12:34');
88
+ });
89
+ it('should handle a date within different years in UTC', () => {
90
+ const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));
91
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
92
+ const end = new Date(Date.UTC(2019, 0, 1, 12, 59, 59));
93
+ assert.equal(formatDateWithinRange(date, start, end, 'UTC'), '2018-01-01 12:34');
94
+ });
95
+ });
96
+ describe('formatDateFriendly()', () => {
97
+ it('should handle a date on the same day at the same time', () => {
98
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
99
+ const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
100
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 12:34pm (UTC)');
101
+ });
102
+ it('should handle a date on the same day at a later time', () => {
103
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
104
+ const date = new Date(Date.UTC(2018, 0, 1, 16, 34, 0));
105
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 4:34pm (UTC)');
106
+ });
107
+ it('should handle a date on the same day at an earlier time', () => {
108
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
109
+ const date = new Date(Date.UTC(2018, 0, 1, 9, 34, 0));
110
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 9:34am (UTC)');
111
+ });
112
+ it('should handle a date on the next day at the same time', () => {
113
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
114
+ const date = new Date(Date.UTC(2018, 0, 2, 12, 34, 0));
115
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'tomorrow, 12:34pm (UTC)');
116
+ });
117
+ it('should handle a date on the next day at a later time', () => {
118
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
119
+ const date = new Date(Date.UTC(2018, 0, 2, 16, 34, 0));
120
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'tomorrow, 4:34pm (UTC)');
121
+ });
122
+ it('should handle a date on the next day at an earlier time', () => {
123
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
124
+ const date = new Date(Date.UTC(2018, 0, 2, 9, 34, 0));
125
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'tomorrow, 9:34am (UTC)');
126
+ });
127
+ it('should handle a date on the previous day at the same time', () => {
128
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
129
+ const date = new Date(Date.UTC(2017, 11, 31, 12, 34, 0));
130
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'yesterday, 12:34pm (UTC)');
131
+ });
132
+ it('should handle a date on the previous day at a later time', () => {
133
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
134
+ const date = new Date(Date.UTC(2017, 11, 31, 16, 34, 0));
135
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'yesterday, 4:34pm (UTC)');
136
+ });
137
+ it('should handle a date on the previous day at an earlier time', () => {
138
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
139
+ const date = new Date(Date.UTC(2017, 11, 31, 9, 34, 0));
140
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'yesterday, 9:34am (UTC)');
141
+ });
142
+ it('should handle a date in the near future', () => {
143
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
144
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
145
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'Sun, Apr\u00a015, 12:34am (UTC)');
146
+ });
147
+ it('should handle a date in the far future', () => {
148
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
149
+ const date = new Date(Date.UTC(2018, 9, 15, 0, 34, 0));
150
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'Mon, Oct\u00a015, 2018, 12:34am (UTC)');
151
+ });
152
+ it('should handle a date in the near past', () => {
153
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
154
+ const date = new Date(Date.UTC(2017, 9, 15, 0, 34, 0));
155
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'Sun, Oct\u00a015, 12:34am (UTC)');
156
+ });
157
+ it('should handle a date in the far past', () => {
158
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
159
+ const date = new Date(Date.UTC(2017, 3, 15, 0, 34, 0));
160
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'Sat, Apr\u00a015, 2017, 12:34am (UTC)');
161
+ });
162
+ it('should display without the timezone', () => {
163
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
164
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
165
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate, includeTz: false }), 'Sun, Apr\u00a015, 12:34am');
166
+ });
167
+ it('should handle a date in CDT', () => {
168
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
169
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
170
+ assert.equal(formatDateFriendly(date, 'America/Chicago', { baseDate }), 'Sat, Apr\u00a014, 7:34pm (CDT)');
171
+ });
172
+ it('should handle a date in CDT without the timezone', () => {
173
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
174
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
175
+ assert.equal(formatDateFriendly(date, 'America/Chicago', { baseDate, includeTz: false }), 'Sat, Apr\u00a014, 7:34pm');
176
+ });
177
+ it('should handle displaying only the date', () => {
178
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
179
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
180
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate, dateOnly: true }), 'Sun, Apr\u00a015 (UTC)');
181
+ });
182
+ it('should handle displaying only the date without the timezone', () => {
183
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
184
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
185
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate, dateOnly: true, includeTz: false }), 'Sun, Apr\u00a015');
186
+ });
187
+ it('should handle displaying only the time', () => {
188
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
189
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
190
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate, timeOnly: true }), '12:34am (UTC)');
191
+ });
192
+ it('should handle displaying only the time without the timezone', () => {
193
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
194
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
195
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate, timeOnly: true, includeTz: false }), '12:34am');
196
+ });
197
+ it('should handle displaying dates with the time first', () => {
198
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
199
+ const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));
200
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate, timeFirst: true }), '12:34am Sun, Apr\u00a015 (UTC)');
201
+ });
202
+ it('should handle a time with seconds', () => {
203
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));
204
+ const date = new Date(Date.UTC(2018, 0, 1, 13, 34, 7));
205
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 1:34:07pm (UTC)');
206
+ });
207
+ it('should handle a time with minutes', () => {
208
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));
209
+ const date = new Date(Date.UTC(2018, 0, 1, 13, 34, 0));
210
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 1:34pm (UTC)');
211
+ });
212
+ it('should handle a time with hours', () => {
213
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));
214
+ const date = new Date(Date.UTC(2018, 0, 1, 13, 0, 0));
215
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 1pm (UTC)');
216
+ });
217
+ it('should handle midnight', () => {
218
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));
219
+ const date = new Date(Date.UTC(2018, 0, 1, 0, 0, 0));
220
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 12am (UTC)');
221
+ });
222
+ it('should handle noon', () => {
223
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));
224
+ const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));
225
+ assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 12pm (UTC)');
226
+ });
227
+ });
228
+ describe('formatDateRangeFriendly()', () => {
229
+ it('should handle two different dates', () => {
230
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
231
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
232
+ const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));
233
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', { baseDate }), 'today, 12:34pm to Wed, Jan\u00a03, 10am (UTC)');
234
+ });
235
+ it('should handle the same date with different times', () => {
236
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
237
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
238
+ const end = new Date(Date.UTC(2018, 0, 1, 13, 0, 0));
239
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', { baseDate }), 'today, 12:34pm to 1pm (UTC)');
240
+ });
241
+ it('should handle the same date with the same time', () => {
242
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
243
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
244
+ const end = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
245
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', { baseDate }), 'today, 12:34pm (UTC)');
246
+ });
247
+ it('should handle two different dates with the time first', () => {
248
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
249
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
250
+ const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));
251
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', { baseDate, timeFirst: true }), '12:34pm today to 10am Wed, Jan\u00a03 (UTC)');
252
+ });
253
+ it('should handle the same date with different times with the time first', () => {
254
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
255
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
256
+ const end = new Date(Date.UTC(2018, 0, 1, 13, 0, 0));
257
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', { baseDate, timeFirst: true }), '12:34pm to 1pm today (UTC)');
258
+ });
259
+ it('should handle the same date with the same time and the time first', () => {
260
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
261
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
262
+ const end = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
263
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', { baseDate, timeFirst: true }), '12:34pm today (UTC)');
264
+ });
265
+ it('should handle two different dates without the timezone', () => {
266
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
267
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
268
+ const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));
269
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', { baseDate, includeTz: false }), 'today, 12:34pm to Wed, Jan\u00a03, 10am');
270
+ });
271
+ it('should handle two different dates with only dates and without the timezone', () => {
272
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
273
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
274
+ const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));
275
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', {
276
+ baseDate,
277
+ dateOnly: true,
278
+ includeTz: false,
279
+ }), 'today to Wed, Jan\u00a03');
280
+ });
281
+ it('should handle two different dates with time first and without the timezone', () => {
282
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
283
+ const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
284
+ const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));
285
+ assert.equal(formatDateRangeFriendly(start, end, 'UTC', {
286
+ baseDate,
287
+ timeFirst: true,
288
+ includeTz: false,
289
+ }), '12:34pm today to 10am Wed, Jan\u00a03');
290
+ });
291
+ it('should handle two different dates in CST', () => {
292
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
293
+ const start = new Date(Date.UTC(2018, 0, 1, 0, 34, 0));
294
+ const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));
295
+ assert.equal(formatDateRangeFriendly(start, end, 'America/Chicago', { baseDate }), 'yesterday, 6:34pm to Wed, Jan\u00a03, 4am (CST)');
296
+ });
297
+ it('should handle two different dates in CDT without the timezone', () => {
298
+ const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));
299
+ const start = new Date(Date.UTC(2018, 0, 1, 0, 34, 0));
300
+ const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));
301
+ assert.equal(formatDateRangeFriendly(start, end, 'America/Chicago', {
302
+ baseDate,
303
+ includeTz: false,
304
+ }), 'yesterday, 6:34pm to Wed, Jan\u00a03, 4am');
305
+ });
306
+ });
70
307
  });
71
308
  //# sourceMappingURL=date.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"date.test.js","sourceRoot":"","sources":["../src/date.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, describe, it } from 'vitest';\n\nimport { formatDate, formatDateYMD, formatDateYMDHM } from './date.js';\n\ndescribe('date formatting', () => {\n describe('formatDate', () => {\n it('formats a UTC date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'UTC'), '2018-01-01 12:00:00 (UTC)');\n });\n it('formats a CST date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'America/Chicago'), '2018-01-01 06:00:00 (CST)');\n });\n it('formats a CDT date', () => {\n const date = new Date(Date.UTC(2018, 6, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'America/Chicago'), '2018-07-01 07:00:00 (CDT)');\n });\n it('formats dates with zero hours', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));\n assert.equal(formatDate(date, 'UTC'), '2018-01-01 00:01:00 (UTC)');\n });\n it('formats dates with milliseconds', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 4, 1, 3, 12));\n assert.equal(formatDate(date, 'UTC', { includeMs: true }), '2018-01-01 04:01:03.012 (UTC)');\n });\n it('formats dates without the timezone', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'UTC', { includeTz: false }), '2018-01-01 12:00:00');\n });\n it('formats dates with the long timezone name', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(\n formatDate(date, 'America/Chicago', { longTz: true }),\n '2018-01-01 06:00:00 (Central Standard Time)',\n );\n });\n });\n\n describe('formatDateYMD()', () => {\n it('should handle a UTC date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDateYMD(date, 'UTC'), '2018-01-01');\n });\n it('should handle a CST date', () => {\n const date = new Date(Date.UTC(2018, 0, 3, 5, 0, 0));\n assert.equal(formatDateYMD(date, 'America/Chicago'), '2018-01-02');\n });\n it('should handle a CDT date', () => {\n const date = new Date(Date.UTC(2018, 6, 1, 12, 0, 0));\n assert.equal(formatDateYMD(date, 'America/Chicago'), '2018-07-01');\n });\n it('should correctly format dates with zero hours', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));\n assert.equal(formatDateYMD(date, 'UTC'), '2018-01-01');\n });\n });\n\n describe('formatDateYMDHM()', () => {\n it('should handle a UTC date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));\n assert.equal(formatDateYMDHM(date, 'UTC'), '2018-01-01 12:34');\n });\n it('should handle a CST date', () => {\n const date = new Date(Date.UTC(2018, 0, 3, 5, 10, 50));\n assert.equal(formatDateYMDHM(date, 'America/Chicago'), '2018-01-02 23:10');\n });\n it('should handle a CDT date', () => {\n const date = new Date(Date.UTC(2018, 6, 1, 19, 8, 19));\n assert.equal(formatDateYMDHM(date, 'America/Chicago'), '2018-07-01 14:08');\n });\n it('should correctly format dates with zero hours', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));\n assert.equal(formatDateYMDHM(date, 'UTC'), '2018-01-01 00:01');\n });\n });\n});\n"]}
1
+ {"version":3,"file":"date.test.js","sourceRoot":"","sources":["../src/date.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, describe, it } from 'vitest';\n\nimport {\n formatDate,\n formatDateFriendly,\n formatDateRangeFriendly,\n formatDateWithinRange,\n formatDateYMD,\n formatDateYMDHM,\n} from './date.js';\n\ndescribe('date formatting', () => {\n describe('formatDate', () => {\n it('formats a UTC date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'UTC'), '2018-01-01 12:00:00 (UTC)');\n });\n it('formats a CST date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'America/Chicago'), '2018-01-01 06:00:00 (CST)');\n });\n it('formats a CDT date', () => {\n const date = new Date(Date.UTC(2018, 6, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'America/Chicago'), '2018-07-01 07:00:00 (CDT)');\n });\n it('formats dates with zero hours', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));\n assert.equal(formatDate(date, 'UTC'), '2018-01-01 00:01:00 (UTC)');\n });\n it('formats dates with milliseconds', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 4, 1, 3, 12));\n assert.equal(formatDate(date, 'UTC', { includeMs: true }), '2018-01-01 04:01:03.012 (UTC)');\n });\n it('formats dates without the timezone', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDate(date, 'UTC', { includeTz: false }), '2018-01-01 12:00:00');\n });\n it('formats dates with the long timezone name', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(\n formatDate(date, 'America/Chicago', { longTz: true }),\n '2018-01-01 06:00:00 (Central Standard Time)',\n );\n });\n });\n\n describe('formatDateYMD()', () => {\n it('should handle a UTC date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDateYMD(date, 'UTC'), '2018-01-01');\n });\n it('should handle a CST date', () => {\n const date = new Date(Date.UTC(2018, 0, 3, 5, 0, 0));\n assert.equal(formatDateYMD(date, 'America/Chicago'), '2018-01-02');\n });\n it('should handle a CDT date', () => {\n const date = new Date(Date.UTC(2018, 6, 1, 12, 0, 0));\n assert.equal(formatDateYMD(date, 'America/Chicago'), '2018-07-01');\n });\n it('should correctly format dates with zero hours', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));\n assert.equal(formatDateYMD(date, 'UTC'), '2018-01-01');\n });\n });\n\n describe('formatDateYMDHM()', () => {\n it('should handle a UTC date', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));\n assert.equal(formatDateYMDHM(date, 'UTC'), '2018-01-01 12:34');\n });\n it('should handle a CST date', () => {\n const date = new Date(Date.UTC(2018, 0, 3, 5, 10, 50));\n assert.equal(formatDateYMDHM(date, 'America/Chicago'), '2018-01-02 23:10');\n });\n it('should handle a CDT date', () => {\n const date = new Date(Date.UTC(2018, 6, 1, 19, 8, 19));\n assert.equal(formatDateYMDHM(date, 'America/Chicago'), '2018-07-01 14:08');\n });\n it('should correctly format dates with zero hours', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 0, 1, 0));\n assert.equal(formatDateYMDHM(date, 'UTC'), '2018-01-01 00:01');\n });\n });\n\n describe('formatDateWithinRange()', () => {\n it('should handle a date within the same day in UTC', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n const end = new Date(Date.UTC(2018, 0, 1, 12, 59, 59));\n assert.equal(formatDateWithinRange(date, start, end, 'UTC'), '12:34');\n });\n it('should handle a date within the same day in CST', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 23, 8, 57));\n const start = new Date(Date.UTC(2018, 0, 1, 21, 0, 0));\n const end = new Date(Date.UTC(2018, 0, 2, 2, 14, 0));\n assert.equal(formatDateWithinRange(date, start, end, 'America/Chicago'), '17:08');\n });\n it('should handle a date within the same year in UTC', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n const end = new Date(Date.UTC(2018, 0, 4, 12, 59, 59));\n assert.equal(formatDateWithinRange(date, start, end, 'UTC'), 'Jan 1, 12:34');\n });\n it('should handle a date within different years in UTC', () => {\n const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 7));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n const end = new Date(Date.UTC(2019, 0, 1, 12, 59, 59));\n assert.equal(formatDateWithinRange(date, start, end, 'UTC'), '2018-01-01 12:34');\n });\n });\n\n describe('formatDateFriendly()', () => {\n it('should handle a date on the same day at the same time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 12:34pm (UTC)');\n });\n\n it('should handle a date on the same day at a later time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 0, 1, 16, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 4:34pm (UTC)');\n });\n\n it('should handle a date on the same day at an earlier time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 0, 1, 9, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 9:34am (UTC)');\n });\n\n it('should handle a date on the next day at the same time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 0, 2, 12, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'tomorrow, 12:34pm (UTC)');\n });\n\n it('should handle a date on the next day at a later time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 0, 2, 16, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'tomorrow, 4:34pm (UTC)');\n });\n\n it('should handle a date on the next day at an earlier time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 0, 2, 9, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'tomorrow, 9:34am (UTC)');\n });\n\n it('should handle a date on the previous day at the same time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2017, 11, 31, 12, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'yesterday, 12:34pm (UTC)');\n });\n\n it('should handle a date on the previous day at a later time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2017, 11, 31, 16, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'yesterday, 4:34pm (UTC)');\n });\n\n it('should handle a date on the previous day at an earlier time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2017, 11, 31, 9, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'yesterday, 9:34am (UTC)');\n });\n\n it('should handle a date in the near future', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate }),\n 'Sun, Apr\\u00a015, 12:34am (UTC)',\n );\n });\n\n it('should handle a date in the far future', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 9, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate }),\n 'Mon, Oct\\u00a015, 2018, 12:34am (UTC)',\n );\n });\n\n it('should handle a date in the near past', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2017, 9, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate }),\n 'Sun, Oct\\u00a015, 12:34am (UTC)',\n );\n });\n\n it('should handle a date in the far past', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2017, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate }),\n 'Sat, Apr\\u00a015, 2017, 12:34am (UTC)',\n );\n });\n\n it('should display without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate, includeTz: false }),\n 'Sun, Apr\\u00a015, 12:34am',\n );\n });\n\n it('should handle a date in CDT', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'America/Chicago', { baseDate }),\n 'Sat, Apr\\u00a014, 7:34pm (CDT)',\n );\n });\n\n it('should handle a date in CDT without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'America/Chicago', { baseDate, includeTz: false }),\n 'Sat, Apr\\u00a014, 7:34pm',\n );\n });\n\n it('should handle displaying only the date', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate, dateOnly: true }),\n 'Sun, Apr\\u00a015 (UTC)',\n );\n });\n\n it('should handle displaying only the date without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate, dateOnly: true, includeTz: false }),\n 'Sun, Apr\\u00a015',\n );\n });\n\n it('should handle displaying only the time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate, timeOnly: true }), '12:34am (UTC)');\n });\n\n it('should handle displaying only the time without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate, timeOnly: true, includeTz: false }),\n '12:34am',\n );\n });\n\n it('should handle displaying dates with the time first', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const date = new Date(Date.UTC(2018, 3, 15, 0, 34, 0));\n assert.equal(\n formatDateFriendly(date, 'UTC', { baseDate, timeFirst: true }),\n '12:34am Sun, Apr\\u00a015 (UTC)',\n );\n });\n\n it('should handle a time with seconds', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));\n const date = new Date(Date.UTC(2018, 0, 1, 13, 34, 7));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 1:34:07pm (UTC)');\n });\n\n it('should handle a time with minutes', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));\n const date = new Date(Date.UTC(2018, 0, 1, 13, 34, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 1:34pm (UTC)');\n });\n\n it('should handle a time with hours', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));\n const date = new Date(Date.UTC(2018, 0, 1, 13, 0, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 1pm (UTC)');\n });\n\n it('should handle midnight', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));\n const date = new Date(Date.UTC(2018, 0, 1, 0, 0, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 12am (UTC)');\n });\n\n it('should handle noon', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 2));\n const date = new Date(Date.UTC(2018, 0, 1, 12, 0, 0));\n assert.equal(formatDateFriendly(date, 'UTC', { baseDate }), 'today, 12pm (UTC)');\n });\n });\n\n describe('formatDateRangeFriendly()', () => {\n it('should handle two different dates', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', { baseDate }),\n 'today, 12:34pm to Wed, Jan\\u00a03, 10am (UTC)',\n );\n });\n\n it('should handle the same date with different times', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 1, 13, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', { baseDate }),\n 'today, 12:34pm to 1pm (UTC)',\n );\n });\n\n it('should handle the same date with the same time', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', { baseDate }),\n 'today, 12:34pm (UTC)',\n );\n });\n\n it('should handle two different dates with the time first', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', { baseDate, timeFirst: true }),\n '12:34pm today to 10am Wed, Jan\\u00a03 (UTC)',\n );\n });\n\n it('should handle the same date with different times with the time first', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 1, 13, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', { baseDate, timeFirst: true }),\n '12:34pm to 1pm today (UTC)',\n );\n });\n\n it('should handle the same date with the same time and the time first', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', { baseDate, timeFirst: true }),\n '12:34pm today (UTC)',\n );\n });\n\n it('should handle two different dates without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', { baseDate, includeTz: false }),\n 'today, 12:34pm to Wed, Jan\\u00a03, 10am',\n );\n });\n\n it('should handle two different dates with only dates and without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', {\n baseDate,\n dateOnly: true,\n includeTz: false,\n }),\n 'today to Wed, Jan\\u00a03',\n );\n });\n\n it('should handle two different dates with time first and without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'UTC', {\n baseDate,\n timeFirst: true,\n includeTz: false,\n }),\n '12:34pm today to 10am Wed, Jan\\u00a03',\n );\n });\n\n it('should handle two different dates in CST', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 0, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'America/Chicago', { baseDate }),\n 'yesterday, 6:34pm to Wed, Jan\\u00a03, 4am (CST)',\n );\n });\n\n it('should handle two different dates in CDT without the timezone', () => {\n const baseDate = new Date(Date.UTC(2018, 0, 1, 12, 34, 0));\n const start = new Date(Date.UTC(2018, 0, 1, 0, 34, 0));\n const end = new Date(Date.UTC(2018, 0, 3, 10, 0, 0));\n assert.equal(\n formatDateRangeFriendly(start, end, 'America/Chicago', {\n baseDate,\n includeTz: false,\n }),\n 'yesterday, 6:34pm to Wed, Jan\\u00a03, 4am',\n );\n });\n });\n});\n"]}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { formatDate, formatDateYMD, formatDateYMDHM, formatTz } from './date.js';
2
- export { formatInterval } from './interval.js';
1
+ export { formatDate, formatDateFriendly, formatDateRangeFriendly, formatDateWithinRange, formatDateYMD, formatDateYMDHM, formatTz, } from './date.js';
2
+ export { formatInterval, formatIntervalHM, formatIntervalMinutes, formatIntervalRelative, makeInterval, } from './interval.js';
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { formatDate, formatDateYMD, formatDateYMDHM, formatTz } from './date.js';
2
- export { formatInterval } from './interval.js';
1
+ export { formatDate, formatDateFriendly, formatDateRangeFriendly, formatDateWithinRange, formatDateYMD, formatDateYMDHM, formatTz, } from './date.js';
2
+ export { formatInterval, formatIntervalHM, formatIntervalMinutes, formatIntervalRelative, makeInterval, } from './interval.js';
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC","sourcesContent":["export { formatDate, formatDateYMD, formatDateYMDHM, formatTz } from './date.js';\nexport { formatInterval } from './interval.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,aAAa,EACb,eAAe,EACf,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,GACb,MAAM,eAAe,CAAC","sourcesContent":["export {\n formatDate,\n formatDateFriendly,\n formatDateRangeFriendly,\n formatDateWithinRange,\n formatDateYMD,\n formatDateYMDHM,\n formatTz,\n} from './date.js';\nexport {\n formatInterval,\n formatIntervalHM,\n formatIntervalMinutes,\n formatIntervalRelative,\n makeInterval,\n} from './interval.js';\n"]}
@@ -2,6 +2,20 @@ export declare const SECOND_IN_MILLISECONDS = 1000;
2
2
  export declare const MINUTE_IN_MILLISECONDS: number;
3
3
  export declare const HOUR_IN_MILLISECONDS: number;
4
4
  export declare const DAY_IN_MILLISECONDS: number;
5
+ /**
6
+ * Makes an interval (in milliseconds).
7
+ *
8
+ * @param param.days The number of days in the interval.
9
+ * @param param.hours The number of hours in the interval.
10
+ * @param param.minutes The number of minutes in the interval.
11
+ * @param param.seconds The number of seconds in the interval.
12
+ */
13
+ export declare function makeInterval({ days, hours, minutes, seconds, }: {
14
+ days?: number;
15
+ hours?: number;
16
+ minutes?: number;
17
+ seconds?: number;
18
+ }): number;
5
19
  /**
6
20
  * Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.
7
21
  *
@@ -9,3 +23,30 @@ export declare const DAY_IN_MILLISECONDS: number;
9
23
  * @returns Human-readable string representing the interval.
10
24
  */
11
25
  export declare function formatInterval(interval: number): string;
26
+ /**
27
+ * Format an interval (in milliseconds) to a human-readable string like 'Until 6
28
+ * minutes before the session start time'.
29
+ *
30
+ * @param interval Time interval in milliseconds relative to `reference` (positive intervals are after `reference`).
31
+ * @param prefix The prefix to use, must be 'Until' or 'From' (or lowercase versions of these).
32
+ * @param reference The reference time, for example 'session start time'.
33
+ * @returns Human-readable string representing the interval.
34
+ */
35
+ export declare function formatIntervalRelative(interval: number, prefix: 'Until' | 'until' | 'From' | 'from', reference: string): string;
36
+ /**
37
+ * Format an interval (in milliseconds) to a human-readable string like HH:MM or +HH:MM.
38
+ *
39
+ * @param interval Time interval in milliseconds.
40
+ * @param options.signed Whether to include the sign in the output.
41
+ * @returns Human-readable string representing the interval in minutes.
42
+ */
43
+ export declare function formatIntervalHM(interval: number, { signed }?: {
44
+ signed?: boolean;
45
+ }): string;
46
+ /**
47
+ * Format an interval (in milliseconds) to a human-readable string with the number of minutes, like '7 minutes' or '1 minute'.
48
+ *
49
+ * @param interval Time interval in milliseconds.
50
+ * @returns Human-readable string representing the interval in minutes.
51
+ */
52
+ export declare function formatIntervalMinutes(interval: number): string;
package/dist/interval.js CHANGED
@@ -2,6 +2,17 @@ export const SECOND_IN_MILLISECONDS = 1000;
2
2
  export const MINUTE_IN_MILLISECONDS = 60 * SECOND_IN_MILLISECONDS;
3
3
  export const HOUR_IN_MILLISECONDS = 60 * MINUTE_IN_MILLISECONDS;
4
4
  export const DAY_IN_MILLISECONDS = 24 * HOUR_IN_MILLISECONDS;
5
+ /**
6
+ * Makes an interval (in milliseconds).
7
+ *
8
+ * @param param.days The number of days in the interval.
9
+ * @param param.hours The number of hours in the interval.
10
+ * @param param.minutes The number of minutes in the interval.
11
+ * @param param.seconds The number of seconds in the interval.
12
+ */
13
+ export function makeInterval({ days = 0, hours = 0, minutes = 0, seconds = 0, }) {
14
+ return (((days * 24 + hours) * 60 + minutes) * 60 + seconds) * 1000;
15
+ }
5
16
  /**
6
17
  * Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.
7
18
  *
@@ -32,4 +43,56 @@ export function formatInterval(interval) {
32
43
  }
33
44
  return parts.join(' ');
34
45
  }
46
+ /**
47
+ * Format an interval (in milliseconds) to a human-readable string like 'Until 6
48
+ * minutes before the session start time'.
49
+ *
50
+ * @param interval Time interval in milliseconds relative to `reference` (positive intervals are after `reference`).
51
+ * @param prefix The prefix to use, must be 'Until' or 'From' (or lowercase versions of these).
52
+ * @param reference The reference time, for example 'session start time'.
53
+ * @returns Human-readable string representing the interval.
54
+ */
55
+ export function formatIntervalRelative(interval, prefix, reference) {
56
+ if (interval > 0) {
57
+ return `${prefix} ${formatInterval(interval)} after ${reference}`;
58
+ }
59
+ else if (interval < 0) {
60
+ return `${prefix} ${formatInterval(-interval)} before ${reference}`;
61
+ }
62
+ else if (interval === 0) {
63
+ return `${prefix} ${reference}`;
64
+ }
65
+ else {
66
+ return `Invalid interval: ${interval}`;
67
+ }
68
+ }
69
+ /**
70
+ * Format an interval (in milliseconds) to a human-readable string like HH:MM or +HH:MM.
71
+ *
72
+ * @param interval Time interval in milliseconds.
73
+ * @param options.signed Whether to include the sign in the output.
74
+ * @returns Human-readable string representing the interval in minutes.
75
+ */
76
+ export function formatIntervalHM(interval, { signed = false } = { signed: false }) {
77
+ const sign = interval < 0 ? '-' : interval > 0 ? (signed ? '+' : '') : '';
78
+ const hours = Math.floor(Math.abs(interval) / HOUR_IN_MILLISECONDS);
79
+ const mins = Math.floor(Math.abs(interval) / MINUTE_IN_MILLISECONDS) % 60;
80
+ return `${sign}${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;
81
+ }
82
+ /**
83
+ * Format an interval (in milliseconds) to a human-readable string with the number of minutes, like '7 minutes' or '1 minute'.
84
+ *
85
+ * @param interval Time interval in milliseconds.
86
+ * @returns Human-readable string representing the interval in minutes.
87
+ */
88
+ export function formatIntervalMinutes(interval) {
89
+ const sign = interval < 0 ? '-' : '';
90
+ const minutes = Math.ceil(Math.abs(interval / MINUTE_IN_MILLISECONDS));
91
+ if (minutes === 1) {
92
+ return `${sign}1 minute`;
93
+ }
94
+ else {
95
+ return `${sign}${minutes} minutes`;
96
+ }
97
+ }
35
98
  //# sourceMappingURL=interval.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"interval.js","sourceRoot":"","sources":["../src/interval.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,GAAG,sBAAsB,CAAC;AAClE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,sBAAsB,CAAC;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,GAAG,oBAAoB,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,IAAI,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAErC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,mBAAmB,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,oBAAoB,CAAC,GAAG,EAAE,CAAC;IACzE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,sBAAsB,CAAC,GAAG,EAAE,CAAC;IAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,sBAAsB,CAAC,GAAG,EAAE,CAAC;IAE1E,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC","sourcesContent":["export const SECOND_IN_MILLISECONDS = 1000;\nexport const MINUTE_IN_MILLISECONDS = 60 * SECOND_IN_MILLISECONDS;\nexport const HOUR_IN_MILLISECONDS = 60 * MINUTE_IN_MILLISECONDS;\nexport const DAY_IN_MILLISECONDS = 24 * HOUR_IN_MILLISECONDS;\n\n/**\n * Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.\n *\n * @param interval Time interval in milliseconds.\n * @returns Human-readable string representing the interval.\n */\nexport function formatInterval(interval: number): string {\n const sign = interval < 0 ? '-' : '';\n\n const days = Math.floor(Math.abs(interval) / DAY_IN_MILLISECONDS);\n const hours = Math.floor(Math.abs(interval) / HOUR_IN_MILLISECONDS) % 24;\n const mins = Math.floor(Math.abs(interval) / MINUTE_IN_MILLISECONDS) % 60;\n const secs = Math.floor(Math.abs(interval) / SECOND_IN_MILLISECONDS) % 60;\n\n const parts: string[] = [];\n\n if (days > 0) {\n parts.push(`${sign}${days} d`);\n }\n if (hours > 0) {\n parts.push(`${sign}${hours} h`);\n }\n if (mins > 0) {\n parts.push(`${sign}${mins} min`);\n }\n if (secs > 0) {\n parts.push(`${sign}${secs} s`);\n }\n if (parts.length === 0) {\n parts.push('0 s');\n }\n\n return parts.join(' ');\n}\n"]}
1
+ {"version":3,"file":"interval.js","sourceRoot":"","sources":["../src/interval.ts"],"names":[],"mappings":"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","sourcesContent":["export const SECOND_IN_MILLISECONDS = 1000;\nexport const MINUTE_IN_MILLISECONDS = 60 * SECOND_IN_MILLISECONDS;\nexport const HOUR_IN_MILLISECONDS = 60 * MINUTE_IN_MILLISECONDS;\nexport const DAY_IN_MILLISECONDS = 24 * HOUR_IN_MILLISECONDS;\n\n/**\n * Makes an interval (in milliseconds).\n *\n * @param param.days The number of days in the interval.\n * @param param.hours The number of hours in the interval.\n * @param param.minutes The number of minutes in the interval.\n * @param param.seconds The number of seconds in the interval.\n */\nexport function makeInterval({\n days = 0,\n hours = 0,\n minutes = 0,\n seconds = 0,\n}: {\n days?: number;\n hours?: number;\n minutes?: number;\n seconds?: number;\n}): number {\n return (((days * 24 + hours) * 60 + minutes) * 60 + seconds) * 1000;\n}\n\n/**\n * Format an interval (in milliseconds) to a human-readable string like '3 h 40 m'.\n *\n * @param interval Time interval in milliseconds.\n * @returns Human-readable string representing the interval.\n */\nexport function formatInterval(interval: number): string {\n const sign = interval < 0 ? '-' : '';\n\n const days = Math.floor(Math.abs(interval) / DAY_IN_MILLISECONDS);\n const hours = Math.floor(Math.abs(interval) / HOUR_IN_MILLISECONDS) % 24;\n const mins = Math.floor(Math.abs(interval) / MINUTE_IN_MILLISECONDS) % 60;\n const secs = Math.floor(Math.abs(interval) / SECOND_IN_MILLISECONDS) % 60;\n\n const parts: string[] = [];\n\n if (days > 0) {\n parts.push(`${sign}${days} d`);\n }\n if (hours > 0) {\n parts.push(`${sign}${hours} h`);\n }\n if (mins > 0) {\n parts.push(`${sign}${mins} min`);\n }\n if (secs > 0) {\n parts.push(`${sign}${secs} s`);\n }\n if (parts.length === 0) {\n parts.push('0 s');\n }\n\n return parts.join(' ');\n}\n\n/**\n * Format an interval (in milliseconds) to a human-readable string like 'Until 6\n * minutes before the session start time'.\n *\n * @param interval Time interval in milliseconds relative to `reference` (positive intervals are after `reference`).\n * @param prefix The prefix to use, must be 'Until' or 'From' (or lowercase versions of these).\n * @param reference The reference time, for example 'session start time'.\n * @returns Human-readable string representing the interval.\n */\nexport function formatIntervalRelative(\n interval: number,\n prefix: 'Until' | 'until' | 'From' | 'from',\n reference: string,\n): string {\n if (interval > 0) {\n return `${prefix} ${formatInterval(interval)} after ${reference}`;\n } else if (interval < 0) {\n return `${prefix} ${formatInterval(-interval)} before ${reference}`;\n } else if (interval === 0) {\n return `${prefix} ${reference}`;\n } else {\n return `Invalid interval: ${interval}`;\n }\n}\n\n/**\n * Format an interval (in milliseconds) to a human-readable string like HH:MM or +HH:MM.\n *\n * @param interval Time interval in milliseconds.\n * @param options.signed Whether to include the sign in the output.\n * @returns Human-readable string representing the interval in minutes.\n */\nexport function formatIntervalHM(\n interval: number,\n { signed = false }: { signed?: boolean } = { signed: false },\n): string {\n const sign = interval < 0 ? '-' : interval > 0 ? (signed ? '+' : '') : '';\n const hours = Math.floor(Math.abs(interval) / HOUR_IN_MILLISECONDS);\n const mins = Math.floor(Math.abs(interval) / MINUTE_IN_MILLISECONDS) % 60;\n return `${sign}${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`;\n}\n\n/**\n * Format an interval (in milliseconds) to a human-readable string with the number of minutes, like '7 minutes' or '1 minute'.\n *\n * @param interval Time interval in milliseconds.\n * @returns Human-readable string representing the interval in minutes.\n */\nexport function formatIntervalMinutes(interval: number): string {\n const sign = interval < 0 ? '-' : '';\n const minutes = Math.ceil(Math.abs(interval / MINUTE_IN_MILLISECONDS));\n if (minutes === 1) {\n return `${sign}1 minute`;\n } else {\n return `${sign}${minutes} minutes`;\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { assert, describe, it } from 'vitest';
2
- import { formatInterval } from './interval.js';
2
+ import { formatInterval, formatIntervalHM, formatIntervalMinutes, formatIntervalRelative, makeInterval, } from './interval.js';
3
3
  describe('interval formatting', () => {
4
4
  describe('formatInterval()', () => {
5
5
  it('should handle seconds', () => {
@@ -27,5 +27,70 @@ describe('interval formatting', () => {
27
27
  assert.equal(formatInterval(-(((4 * 24 + 3) * 60 + 2) * 60 + 7) * 1000), '-4 d -3 h -2 min -7 s');
28
28
  });
29
29
  });
30
+ describe('formatIntervalRelative()', () => {
31
+ it('should handle positive intervals', () => {
32
+ assert.equal(formatIntervalRelative(3 * 1000, 'Until', 'the start time'), 'Until 3 s after the start time');
33
+ });
34
+ it('should handle negative intervals', () => {
35
+ assert.equal(formatIntervalRelative(-7 * 60 * 1000, 'From', 'the start time'), 'From 7 min before the start time');
36
+ });
37
+ it('should handle zero intervals', () => {
38
+ assert.equal(formatIntervalRelative(0, 'From', 'the start time'), 'From the start time');
39
+ });
40
+ });
41
+ describe('formatIntervalMinutes()', () => {
42
+ it('should correctly round up', () => {
43
+ assert.equal(formatIntervalMinutes(3.2 * 60 * 1000), '4 minutes');
44
+ });
45
+ it('should correctly handle 1 minute', () => {
46
+ assert.equal(formatIntervalMinutes(17 * 1000), '1 minute');
47
+ });
48
+ it('should correctly handle zero', () => {
49
+ assert.equal(formatIntervalMinutes(0), '0 minutes');
50
+ });
51
+ it('should correctly handle -1 minute', () => {
52
+ assert.equal(formatIntervalMinutes(-17 * 1000), '-1 minute');
53
+ });
54
+ it('should correctly handle negative intervals', () => {
55
+ assert.equal(formatIntervalMinutes(-3.2 * 60 * 1000), '-4 minutes');
56
+ });
57
+ });
58
+ describe('formatIntervalHM()', () => {
59
+ it('should correctly handle postive minutes', () => {
60
+ assert.equal(formatIntervalHM(3.2 * 60 * 1000), '00:03');
61
+ });
62
+ it('should correctly handle postive hours', () => {
63
+ assert.equal(formatIntervalHM((4 * 60 + 17.8) * 60 * 1000), '04:17');
64
+ });
65
+ it('should correctly handle large postive hours', () => {
66
+ assert.equal(formatIntervalHM((143 * 60 + 17.8) * 60 * 1000), '143:17');
67
+ });
68
+ it('should correctly handle an explicit sign', () => {
69
+ assert.equal(formatIntervalHM((4 * 60 + 17.8) * 60 * 1000, { signed: true }), '+04:17');
70
+ });
71
+ it('should correctly handle negative minutes', () => {
72
+ assert.equal(formatIntervalHM(-3.2 * 60 * 1000), '-00:03');
73
+ });
74
+ it('should correctly handle negative hours', () => {
75
+ assert.equal(formatIntervalHM(-(4 * 60 + 17.8) * 60 * 1000), '-04:17');
76
+ });
77
+ });
78
+ describe('makeInterval()', () => {
79
+ it('should handle seconds', () => {
80
+ assert.equal(makeInterval({ seconds: 7 }), 7 * 1000);
81
+ });
82
+ it('should handle minutes', () => {
83
+ assert.equal(makeInterval({ minutes: 2 }), 2 * 60 * 1000);
84
+ });
85
+ it('should handle hours', () => {
86
+ assert.equal(makeInterval({ hours: 3 }), 3 * 60 * 60 * 1000);
87
+ });
88
+ it('should handle days', () => {
89
+ assert.equal(makeInterval({ days: 4 }), 4 * 24 * 60 * 60 * 1000);
90
+ });
91
+ it('should default to zero', () => {
92
+ assert.equal(makeInterval({}), 0);
93
+ });
94
+ });
30
95
  });
31
96
  //# sourceMappingURL=interval.test.js.map