@discomedia/utils 1.0.19 → 1.0.21

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/index.cjs CHANGED
@@ -162,6 +162,11 @@ const MARKET_CONFIG = {
162
162
  },
163
163
  };
164
164
  // Helper: Get NY offset for a given UTC date (DST rules for US)
165
+ /**
166
+ * Returns the NY timezone offset (in hours) for a given UTC date, accounting for US DST rules.
167
+ * @param date - UTC date
168
+ * @returns offset in hours (-5 for EST, -4 for EDT)
169
+ */
165
170
  function getNYOffset(date) {
166
171
  // US DST starts 2nd Sunday in March, ends 1st Sunday in November
167
172
  const year = date.getUTCFullYear();
@@ -174,6 +179,14 @@ function getNYOffset(date) {
174
179
  return MARKET_CONFIG.UTC_OFFSET_STANDARD;
175
180
  }
176
181
  // Helper: Get nth weekday of month in UTC
182
+ /**
183
+ * Returns the nth weekday of a given month in UTC.
184
+ * @param year - Year
185
+ * @param month - 1-based month (e.g. March = 3)
186
+ * @param weekday - 0=Sunday, 1=Monday, ...
187
+ * @param n - nth occurrence
188
+ * @returns Date object for the nth weekday
189
+ */
177
190
  function getNthWeekdayOfMonth(year, month, weekday, n) {
178
191
  let count = 0;
179
192
  for (let d = 1; d <= 31; d++) {
@@ -190,6 +203,11 @@ function getNthWeekdayOfMonth(year, month, weekday, n) {
190
203
  return new Date(Date.UTC(year, month - 1, 28));
191
204
  }
192
205
  // Helper: Convert UTC date to NY time (returns new Date object)
206
+ /**
207
+ * Converts a UTC date to NY time (returns a new Date object).
208
+ * @param date - UTC date
209
+ * @returns Date object in NY time
210
+ */
193
211
  function toNYTime(date) {
194
212
  const offset = getNYOffset(date);
195
213
  // NY offset in hours
@@ -198,6 +216,11 @@ function toNYTime(date) {
198
216
  return new Date(nyMillis);
199
217
  }
200
218
  // Helper: Convert NY time to UTC (returns new Date object)
219
+ /**
220
+ * Converts a NY time date to UTC (returns a new Date object).
221
+ * @param date - NY time date
222
+ * @returns Date object in UTC
223
+ */
201
224
  function fromNYTime(date) {
202
225
  const offset = getNYOffset(date);
203
226
  const nyMillis = date.getTime();
@@ -205,6 +228,12 @@ function fromNYTime(date) {
205
228
  return new Date(utcMillis);
206
229
  }
207
230
  // Helper: Format date in ISO, unix, etc.
231
+ /**
232
+ * Formats a date in ISO, unix-seconds, or unix-ms format.
233
+ * @param date - Date object
234
+ * @param outputFormat - Output format ('iso', 'unix-seconds', 'unix-ms')
235
+ * @returns Formatted date string or number
236
+ */
208
237
  function formatDate(date, outputFormat = 'iso') {
209
238
  switch (outputFormat) {
210
239
  case 'unix-seconds':
@@ -217,15 +246,33 @@ function formatDate(date, outputFormat = 'iso') {
217
246
  }
218
247
  }
219
248
  // Helper: Format date in NY locale string
249
+ /**
250
+ * Formats a date in NY locale string.
251
+ * @param date - Date object
252
+ * @returns NY locale string
253
+ */
220
254
  function formatNYLocale(date) {
221
255
  return date.toLocaleString('en-US', { timeZone: 'America/New_York' });
222
256
  }
223
257
  // Market calendar logic
258
+ /**
259
+ * Market calendar logic for holidays, weekends, and market days.
260
+ */
224
261
  class MarketCalendar {
262
+ /**
263
+ * Checks if a date is a weekend in NY time.
264
+ * @param date - Date object
265
+ * @returns true if weekend, false otherwise
266
+ */
225
267
  isWeekend(date) {
226
268
  const day = toNYTime(date).getUTCDay();
227
269
  return day === 0 || day === 6;
228
270
  }
271
+ /**
272
+ * Checks if a date is a market holiday in NY time.
273
+ * @param date - Date object
274
+ * @returns true if holiday, false otherwise
275
+ */
229
276
  isHoliday(date) {
230
277
  const nyDate = toNYTime(date);
231
278
  const year = nyDate.getUTCFullYear();
@@ -235,8 +282,13 @@ class MarketCalendar {
235
282
  const yearHolidays = marketHolidays[year];
236
283
  if (!yearHolidays)
237
284
  return false;
238
- return Object.values(yearHolidays).some(holiday => holiday.date === formattedDate);
285
+ return Object.values(yearHolidays).some((holiday) => holiday.date === formattedDate);
239
286
  }
287
+ /**
288
+ * Checks if a date is an early close day in NY time.
289
+ * @param date - Date object
290
+ * @returns true if early close, false otherwise
291
+ */
240
292
  isEarlyCloseDay(date) {
241
293
  const nyDate = toNYTime(date);
242
294
  const year = nyDate.getUTCFullYear();
@@ -246,6 +298,11 @@ class MarketCalendar {
246
298
  const yearEarlyCloses = marketEarlyCloses[year];
247
299
  return yearEarlyCloses && yearEarlyCloses[formattedDate] !== undefined;
248
300
  }
301
+ /**
302
+ * Gets the early close time (in minutes from midnight) for a given date.
303
+ * @param date - Date object
304
+ * @returns minutes from midnight or null
305
+ */
249
306
  getEarlyCloseTime(date) {
250
307
  const nyDate = toNYTime(date);
251
308
  const year = nyDate.getUTCFullYear();
@@ -259,9 +316,19 @@ class MarketCalendar {
259
316
  }
260
317
  return null;
261
318
  }
319
+ /**
320
+ * Checks if a date is a market day (not weekend or holiday).
321
+ * @param date - Date object
322
+ * @returns true if market day, false otherwise
323
+ */
262
324
  isMarketDay(date) {
263
325
  return !this.isWeekend(date) && !this.isHoliday(date);
264
326
  }
327
+ /**
328
+ * Gets the next market day after the given date.
329
+ * @param date - Date object
330
+ * @returns Date object for next market day
331
+ */
265
332
  getNextMarketDay(date) {
266
333
  let nextDay = new Date(date.getTime() + 24 * 60 * 60 * 1000);
267
334
  while (!this.isMarketDay(nextDay)) {
@@ -269,6 +336,11 @@ class MarketCalendar {
269
336
  }
270
337
  return nextDay;
271
338
  }
339
+ /**
340
+ * Gets the previous market day before the given date.
341
+ * @param date - Date object
342
+ * @returns Date object for previous market day
343
+ */
272
344
  getPreviousMarketDay(date) {
273
345
  let prevDay = new Date(date.getTime() - 24 * 60 * 60 * 1000);
274
346
  while (!this.isMarketDay(prevDay)) {
@@ -278,6 +350,11 @@ class MarketCalendar {
278
350
  }
279
351
  }
280
352
  // Market open/close times
353
+ /**
354
+ * Returns market open/close times for a given date, including extended and early closes.
355
+ * @param date - Date object
356
+ * @returns MarketOpenCloseResult
357
+ */
281
358
  function getMarketTimes(date) {
282
359
  const calendar = new MarketCalendar();
283
360
  const nyDate = toNYTime(date);
@@ -315,7 +392,13 @@ function getMarketTimes(date) {
315
392
  };
316
393
  }
317
394
  // Is within market hours
318
- function isWithinMarketHoursImpl(date, intradayReporting = 'market_hours') {
395
+ /**
396
+ * Checks if a date/time is within market hours, extended hours, or continuous.
397
+ * @param date - Date object
398
+ * @param intradayReporting - 'market_hours', 'extended_hours', or 'continuous'
399
+ * @returns true if within hours, false otherwise
400
+ */
401
+ function isWithinMarketHours(date, intradayReporting = 'market_hours') {
319
402
  const calendar = new MarketCalendar();
320
403
  if (!calendar.isMarketDay(date))
321
404
  return false;
@@ -343,6 +426,11 @@ function isWithinMarketHoursImpl(date, intradayReporting = 'market_hours') {
343
426
  }
344
427
  }
345
428
  // Get last full trading date
429
+ /**
430
+ * Returns the last full trading date (market close) for a given date.
431
+ * @param currentDate - Date object (default: now)
432
+ * @returns Date object for last full trading date
433
+ */
346
434
  function getLastFullTradingDateImpl(currentDate = new Date()) {
347
435
  const calendar = new MarketCalendar();
348
436
  const nyDate = toNYTime(currentDate);
@@ -353,7 +441,9 @@ function getLastFullTradingDateImpl(currentDate = new Date()) {
353
441
  marketCloseMinutes = MARKET_CONFIG.TIMES.EARLY_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.EARLY_CLOSE.minute;
354
442
  }
355
443
  // If not a market day, or before open, or during market hours, return previous market day's close
356
- if (!calendar.isMarketDay(currentDate) || minutes < marketOpenMinutes || (minutes >= marketOpenMinutes && minutes < marketCloseMinutes)) {
444
+ if (!calendar.isMarketDay(currentDate) ||
445
+ minutes < marketOpenMinutes ||
446
+ (minutes >= marketOpenMinutes && minutes < marketCloseMinutes)) {
357
447
  const prevMarketDay = calendar.getPreviousMarketDay(currentDate);
358
448
  let prevCloseMinutes = MARKET_CONFIG.TIMES.MARKET_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.MARKET_CLOSE.minute;
359
449
  if (calendar.isEarlyCloseDay(prevMarketDay)) {
@@ -375,6 +465,12 @@ function getLastFullTradingDateImpl(currentDate = new Date()) {
375
465
  return fromNYTime(new Date(Date.UTC(year, month, day, closeHour, closeMinute, 0, 0)));
376
466
  }
377
467
  // Get day boundaries
468
+ /**
469
+ * Returns the start and end boundaries for a market day, extended hours, or continuous.
470
+ * @param date - Date object
471
+ * @param intradayReporting - 'market_hours', 'extended_hours', or 'continuous'
472
+ * @returns Object with start and end Date
473
+ */
378
474
  function getDayBoundaries(date, intradayReporting = 'market_hours') {
379
475
  const calendar = new MarketCalendar();
380
476
  const nyDate = toNYTime(date);
@@ -410,6 +506,12 @@ function getDayBoundaries(date, intradayReporting = 'market_hours') {
410
506
  return { start, end };
411
507
  }
412
508
  // Period calculator
509
+ /**
510
+ * Calculates the start date for a given period ending at endDate.
511
+ * @param endDate - Date object
512
+ * @param period - Period string
513
+ * @returns Date object for period start
514
+ */
413
515
  function calculatePeriodStartDate(endDate, period) {
414
516
  const calendar = new MarketCalendar();
415
517
  let startDate;
@@ -451,8 +553,13 @@ function calculatePeriodStartDate(endDate, period) {
451
553
  return startDate;
452
554
  }
453
555
  // Get market time period
556
+ /**
557
+ * Returns the start and end dates for a market time period.
558
+ * @param params - MarketTimeParams
559
+ * @returns PeriodDates object
560
+ */
454
561
  function getMarketTimePeriod(params) {
455
- const { period, end = new Date(), intraday_reporting = 'market_hours', outputFormat = 'iso', } = params;
562
+ const { period, end = new Date(), intraday_reporting = 'market_hours', outputFormat = 'iso' } = params;
456
563
  if (!period)
457
564
  throw new Error('Period is required');
458
565
  const calendar = new MarketCalendar();
@@ -497,6 +604,11 @@ function getMarketTimePeriod(params) {
497
604
  };
498
605
  }
499
606
  // Market status
607
+ /**
608
+ * Returns the current market status for a given date.
609
+ * @param date - Date object (default: now)
610
+ * @returns MarketStatus object
611
+ */
500
612
  function getMarketStatusImpl(date = new Date()) {
501
613
  const calendar = new MarketCalendar();
502
614
  const nyDate = toNYTime(date);
@@ -510,7 +622,8 @@ function getMarketStatusImpl(date = new Date()) {
510
622
  let extendedEndMinutes = MARKET_CONFIG.TIMES.EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EXTENDED_END.minute;
511
623
  if (isEarlyCloseDay) {
512
624
  marketCloseMinutes = MARKET_CONFIG.TIMES.EARLY_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.EARLY_CLOSE.minute;
513
- extendedEndMinutes = MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.minute;
625
+ extendedEndMinutes =
626
+ MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.minute;
514
627
  }
515
628
  let status;
516
629
  let nextStatus;
@@ -567,10 +680,20 @@ function getMarketStatusImpl(date = new Date()) {
567
680
  };
568
681
  }
569
682
  // API exports
683
+ /**
684
+ * Returns market open/close times for a given date.
685
+ * @param options - { date?: Date }
686
+ * @returns MarketOpenCloseResult
687
+ */
570
688
  function getMarketOpenClose(options = {}) {
571
689
  const { date = new Date() } = options;
572
690
  return getMarketTimes(date);
573
691
  }
692
+ /**
693
+ * Returns the start and end dates for a market time period as Date objects.
694
+ * @param params - MarketTimeParams
695
+ * @returns Object with start and end Date
696
+ */
574
697
  function getStartAndEndDates(params = {}) {
575
698
  const { start, end } = getMarketTimePeriod(params);
576
699
  return {
@@ -581,46 +704,103 @@ function getStartAndEndDates(params = {}) {
581
704
  /**
582
705
  * Returns the last full trading date as a Date object.
583
706
  */
707
+ /**
708
+ * Returns the last full trading date as a Date object.
709
+ * @param currentDate - Date object (default: now)
710
+ * @returns Date object for last full trading date
711
+ */
584
712
  function getLastFullTradingDate(currentDate = new Date()) {
585
713
  return getLastFullTradingDateImpl(currentDate);
586
714
  }
715
+ /**
716
+ * Returns the next market day after the reference date.
717
+ * @param referenceDate - Date object (default: now)
718
+ * @returns Object with date, yyyymmdd string, and ISO string
719
+ */
587
720
  function getNextMarketDay({ referenceDate } = {}) {
588
721
  const calendar = new MarketCalendar();
589
- const startDate = referenceDate || new Date();
722
+ const startDate = referenceDate ?? new Date();
723
+ // Find the next trading day (UTC Date object)
590
724
  const nextDate = calendar.getNextMarketDay(startDate);
591
- const yyyymmdd = `${nextDate.getUTCFullYear()}-${String(nextDate.getUTCMonth() + 1).padStart(2, '0')}-${String(nextDate.getUTCDate()).padStart(2, '0')}`;
725
+ // Convert to NY time before extracting Y-M-D parts
726
+ const nyNext = toNYTime(nextDate);
727
+ const yyyymmdd = `${nyNext.getUTCFullYear()}-${String(nyNext.getUTCMonth() + 1).padStart(2, '0')}-${String(nyNext.getUTCDate()).padStart(2, '0')}`;
592
728
  return {
593
- date: nextDate,
594
- yyyymmdd,
729
+ date: nextDate, // raw Date, unchanged
730
+ yyyymmdd, // correct trading date string
595
731
  dateISOString: nextDate.toISOString(),
596
732
  };
597
733
  }
734
+ /**
735
+ * Returns the previous market day before the reference date.
736
+ * @param referenceDate - Date object (default: now)
737
+ * @returns Object with date, yyyymmdd string, and ISO string
738
+ */
739
+ function getPreviousMarketDay({ referenceDate } = {}) {
740
+ const calendar = new MarketCalendar();
741
+ const startDate = referenceDate || new Date();
742
+ const prevDate = calendar.getPreviousMarketDay(startDate);
743
+ // convert to NY time first
744
+ const nyPrev = toNYTime(prevDate); // ← already in this file
745
+ const yyyymmdd = `${nyPrev.getUTCFullYear()}-${String(nyPrev.getUTCMonth() + 1).padStart(2, '0')}-${String(nyPrev.getUTCDate()).padStart(2, '0')}`;
746
+ return {
747
+ date: prevDate,
748
+ yyyymmdd,
749
+ dateISOString: prevDate.toISOString(),
750
+ };
751
+ }
598
752
  /**
599
753
  * Returns the trading date for a given time. Note: Just trims the date string; does not validate if the date is a market day.
600
754
  * @param time - a string, number (unix timestamp), or Date object representing the time
601
755
  * @returns the trading date as a string in YYYY-MM-DD format
602
756
  */
757
+ /**
758
+ * Returns the trading date for a given time in YYYY-MM-DD format (NY time).
759
+ * @param time - string, number, or Date
760
+ * @returns trading date string
761
+ */
603
762
  function getTradingDate(time) {
604
763
  const date = typeof time === 'number' ? new Date(time) : typeof time === 'string' ? new Date(time) : time;
605
764
  const nyDate = toNYTime(date);
606
765
  return `${nyDate.getUTCFullYear()}-${String(nyDate.getUTCMonth() + 1).padStart(2, '0')}-${String(nyDate.getUTCDate()).padStart(2, '0')}`;
607
766
  }
767
+ /**
768
+ * Returns the NY timezone offset string for a given date.
769
+ * @param date - Date object (default: now)
770
+ * @returns '-04:00' for EDT, '-05:00' for EST
771
+ */
608
772
  function getNYTimeZone(date) {
609
773
  const offset = getNYOffset(date || new Date());
610
774
  return offset === -4 ? '-04:00' : '-05:00';
611
775
  }
776
+ /**
777
+ * Returns the current market status for a given date.
778
+ * @param options - { date?: Date }
779
+ * @returns MarketStatus object
780
+ */
612
781
  function getMarketStatus(options = {}) {
613
782
  const { date = new Date() } = options;
614
783
  return getMarketStatusImpl(date);
615
784
  }
616
- function isWithinMarketHours(date, intradayReporting = 'market_hours') {
617
- return isWithinMarketHoursImpl(date, intradayReporting);
785
+ /**
786
+ * Checks if a date is a market day.
787
+ * @param date - Date object
788
+ * @returns true if market day, false otherwise
789
+ */
790
+ function isMarketDay(date) {
791
+ const calendar = new MarketCalendar();
792
+ return calendar.isMarketDay(date);
618
793
  }
619
794
  /**
620
795
  * Returns full trading days from market open to market close.
621
796
  * endDate is always the most recent market close (previous day's close if before open, today's close if after open).
622
797
  * days: 1 or not specified = that day's open; 2 = previous market day's open, etc.
623
798
  */
799
+ /**
800
+ * Returns full trading days from market open to market close.
801
+ * @param options - { endDate?: Date, days?: number }
802
+ * @returns Object with startDate and endDate
803
+ */
624
804
  function getTradingStartAndEndDates(options = {}) {
625
805
  const { endDate = new Date(), days = 1 } = options;
626
806
  const calendar = new MarketCalendar();
@@ -630,7 +810,9 @@ function getTradingStartAndEndDates(options = {}) {
630
810
  const marketOpenMinutes = MARKET_CONFIG.TIMES.MARKET_OPEN.hour * 60 + MARKET_CONFIG.TIMES.MARKET_OPEN.minute;
631
811
  const marketCloseMinutes = MARKET_CONFIG.TIMES.MARKET_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.MARKET_CLOSE.minute;
632
812
  const minutes = nyEnd.getUTCHours() * 60 + nyEnd.getUTCMinutes();
633
- if (!calendar.isMarketDay(endDate) || minutes < marketOpenMinutes || (minutes >= marketOpenMinutes && minutes < marketCloseMinutes)) {
813
+ if (!calendar.isMarketDay(endDate) ||
814
+ minutes < marketOpenMinutes ||
815
+ (minutes >= marketOpenMinutes && minutes < marketCloseMinutes)) {
634
816
  // Before market open, not a market day, or during market hours: use previous market day
635
817
  endMarketDay = calendar.getPreviousMarketDay(endDate);
636
818
  }
@@ -656,32 +838,102 @@ function getTradingStartAndEndDates(options = {}) {
656
838
  const startOpen = getMarketOpenClose({ date: startMarketDay }).open;
657
839
  return { startDate: startOpen, endDate: endClose };
658
840
  }
841
+ /**
842
+ * Counts trading time between two dates (passed as standard Date objects), excluding weekends and holidays, and closed market hours, using other functions in this library.
843
+ *
844
+ * This function calculates the actual trading time between two dates by:
845
+ * 1. Iterating through each calendar day between startDate and endDate (inclusive)
846
+ * 2. For each day that is a market day (not weekend/holiday), getting market open/close times
847
+ * 3. Calculating the overlap between the time range and market hours for that day
848
+ * 4. Summing up all the trading minutes across all days
849
+ *
850
+ * The function automatically handles:
851
+ * - Weekends (Saturday/Sunday) - skipped entirely
852
+ * - Market holidays - skipped entirely
853
+ * - Early close days (e.g. day before holidays) - uses early close time
854
+ * - Times outside market hours - only counts time within 9:30am-4pm ET (or early close)
855
+ *
856
+ * Examples:
857
+ * - 12pm to 3:30pm same day = 3.5 hours = 210 minutes = 0.54 days
858
+ * - 9:30am to 4pm same day = 6.5 hours = 390 minutes = 1 day
859
+ * - Friday 2pm to Monday 2pm = 6.5 hours (Friday 2pm-4pm + Monday 9:30am-2pm)
860
+ *
861
+ * @param startDate - Start date/time
862
+ * @param endDate - End date/time (default: now)
863
+ * @returns Object containing:
864
+ * - days: Trading time as fraction of full trading days (6.5 hours = 1 day)
865
+ * - hours: Trading time in hours
866
+ * - minutes: Trading time in minutes
867
+ */
868
+ function countTradingDays(startDate, endDate = new Date()) {
869
+ const calendar = new MarketCalendar();
870
+ // Ensure start is before end
871
+ if (startDate.getTime() > endDate.getTime()) {
872
+ throw new Error('Start date must be before end date');
873
+ }
874
+ let totalMinutes = 0;
875
+ // Get the NY dates for iteration
876
+ const startNY = toNYTime(startDate);
877
+ const endNY = toNYTime(endDate);
878
+ // Create date at start of first day (in NY time)
879
+ const currentNY = new Date(Date.UTC(startNY.getUTCFullYear(), startNY.getUTCMonth(), startNY.getUTCDate(), 0, 0, 0, 0));
880
+ // Iterate through each calendar day
881
+ while (currentNY.getTime() <= endNY.getTime()) {
882
+ const currentUTC = fromNYTime(currentNY);
883
+ // Check if this is a market day
884
+ if (calendar.isMarketDay(currentUTC)) {
885
+ // Get market hours for this day
886
+ const marketTimes = getMarketTimes(currentUTC);
887
+ if (marketTimes.marketOpen && marketTimes.open && marketTimes.close) {
888
+ // Calculate the overlap between our time range and market hours
889
+ const dayStart = Math.max(startDate.getTime(), marketTimes.open.getTime());
890
+ const dayEnd = Math.min(endDate.getTime(), marketTimes.close.getTime());
891
+ // Only count if there's actual overlap
892
+ if (dayStart < dayEnd) {
893
+ totalMinutes += (dayEnd - dayStart) / (1000 * 60);
894
+ }
895
+ }
896
+ }
897
+ // Move to next day
898
+ currentNY.setUTCDate(currentNY.getUTCDate() + 1);
899
+ }
900
+ // Convert to days, hours, minutes
901
+ const MINUTES_PER_TRADING_DAY = 390; // 6.5 hours
902
+ const days = totalMinutes / MINUTES_PER_TRADING_DAY;
903
+ const hours = totalMinutes / 60;
904
+ const minutes = totalMinutes;
905
+ return {
906
+ days: Math.round(days * 1000) / 1000, // Round to 3 decimal places
907
+ hours: Math.round(hours * 100) / 100, // Round to 2 decimal places
908
+ minutes: Math.round(minutes),
909
+ };
910
+ }
659
911
  // Export MARKET_TIMES for compatibility
660
912
  const MARKET_TIMES = {
661
913
  TIMEZONE: MARKET_CONFIG.TIMEZONE,
662
914
  PRE: {
663
915
  START: { HOUR: 4, MINUTE: 0, MINUTES: 240 },
664
- END: { HOUR: 9, MINUTE: 30, MINUTES: 570 }
916
+ END: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
665
917
  },
666
918
  EARLY_MORNING: {
667
919
  START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
668
- END: { HOUR: 10, MINUTE: 0, MINUTES: 600 }
920
+ END: { HOUR: 10, MINUTE: 0, MINUTES: 600 },
669
921
  },
670
922
  EARLY_CLOSE_BEFORE_HOLIDAY: {
671
923
  START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
672
- END: { HOUR: 13, MINUTE: 0, MINUTES: 780 }
924
+ END: { HOUR: 13, MINUTE: 0, MINUTES: 780 },
673
925
  },
674
926
  EARLY_EXTENDED_BEFORE_HOLIDAY: {
675
927
  START: { HOUR: 13, MINUTE: 0, MINUTES: 780 },
676
- END: { HOUR: 17, MINUTE: 0, MINUTES: 1020 }
928
+ END: { HOUR: 17, MINUTE: 0, MINUTES: 1020 },
677
929
  },
678
930
  REGULAR: {
679
931
  START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
680
- END: { HOUR: 16, MINUTE: 0, MINUTES: 960 }
932
+ END: { HOUR: 16, MINUTE: 0, MINUTES: 960 },
681
933
  },
682
934
  EXTENDED: {
683
935
  START: { HOUR: 4, MINUTE: 0, MINUTES: 240 },
684
- END: { HOUR: 20, MINUTE: 0, MINUTES: 1200 }
936
+ END: { HOUR: 20, MINUTE: 0, MINUTES: 1200 },
685
937
  },
686
938
  };
687
939
 
@@ -1083,6 +1335,12 @@ class Queue {
1083
1335
  current = current.next;
1084
1336
  }
1085
1337
  }
1338
+
1339
+ * drain() {
1340
+ while (this.#head) {
1341
+ yield this.dequeue();
1342
+ }
1343
+ }
1086
1344
  }
1087
1345
 
1088
1346
  function pLimit(concurrency) {
@@ -2112,7 +2370,7 @@ const safeJSON = (text) => {
2112
2370
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2113
2371
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2114
2372
 
2115
- const VERSION = '5.10.1'; // x-release-please-version
2373
+ const VERSION = '5.10.2'; // x-release-please-version
2116
2374
 
2117
2375
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2118
2376
  const isRunningInBrowser = () => {
@@ -15232,7 +15490,7 @@ var config = {};
15232
15490
 
15233
15491
  var main = {exports: {}};
15234
15492
 
15235
- var version = "17.2.0";
15493
+ var version = "17.2.1";
15236
15494
  var require$$4 = {
15237
15495
  version: version};
15238
15496
 
@@ -15251,9 +15509,12 @@ function requireMain () {
15251
15509
 
15252
15510
  // Array of tips to display randomly
15253
15511
  const TIPS = [
15254
- '🔐 encrypt with dotenvx: https://dotenvx.com',
15512
+ '🔐 encrypt with Dotenvx: https://dotenvx.com',
15255
15513
  '🔐 prevent committing .env to code: https://dotenvx.com/precommit',
15256
15514
  '🔐 prevent building .env in docker: https://dotenvx.com/prebuild',
15515
+ '📡 observe env with Radar: https://dotenvx.com/radar',
15516
+ '📡 auto-backup env with Radar: https://dotenvx.com/radar',
15517
+ '📡 version env with Radar: https://dotenvx.com/radar',
15257
15518
  '🛠️ run anywhere with `dotenvx run -- yourcommand`',
15258
15519
  '⚙️ specify custom .env file path with { path: \'/custom/path/.env\' }',
15259
15520
  '⚙️ enable debug logging with { debug: true }',
@@ -15554,7 +15815,7 @@ function requireMain () {
15554
15815
  }
15555
15816
  }
15556
15817
 
15557
- _log(`injecting env (${keysCount}) from ${shortPaths.join(',')} ${dim(`(tip: ${_getRandomTip()})`)}`);
15818
+ _log(`injecting env (${keysCount}) from ${shortPaths.join(',')} ${dim(`-- tip: ${_getRandomTip()}`)}`);
15558
15819
  }
15559
15820
 
15560
15821
  if (lastError) {
@@ -18035,10 +18296,15 @@ const disco = {
18035
18296
  getMarketOpenClose: getMarketOpenClose,
18036
18297
  getLastFullTradingDate: getLastFullTradingDate,
18037
18298
  getNextMarketDay: getNextMarketDay,
18299
+ getPreviousMarketDay: getPreviousMarketDay,
18300
+ getMarketTimePeriod: getMarketTimePeriod,
18038
18301
  getMarketStatus: getMarketStatus,
18039
18302
  getNYTimeZone: getNYTimeZone,
18040
18303
  getTradingDate: getTradingDate,
18041
18304
  getTradingStartAndEndDates: getTradingStartAndEndDates,
18305
+ isMarketDay: isMarketDay,
18306
+ isWithinMarketHours: isWithinMarketHours,
18307
+ countTradingDays: countTradingDays,
18042
18308
  MARKET_TIMES: MARKET_TIMES,
18043
18309
  },
18044
18310
  utils: {