utils.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import {getFormat} from 'sentry/utils/dates';
  2. import type {TimeWindow, TimeWindowConfig} from './types';
  3. // Stores the elapsed minutes for each selectable resolution
  4. export const resolutionElapsedMinutes: Record<TimeWindow, number> = {
  5. '1h': 60,
  6. '24h': 60 * 24,
  7. '7d': 60 * 24 * 7,
  8. '30d': 60 * 24 * 30,
  9. };
  10. /**
  11. * The minimum pixels to allocate to the reference start time label which
  12. * always includes date, time, and timezone.
  13. */
  14. const TIMELABEL_WIDTH_FULL = 115;
  15. /**
  16. * The minimum pixels to allocate to each time label when it is a full date.
  17. */
  18. const TIMELABEL_WIDTH_DATE = 110;
  19. /**
  20. * The minimum pixels to allocate to each time label when it's a timestaamp.
  21. */
  22. const TIMELABEL_WIDTH_TIME = 100;
  23. const ONE_HOUR = 60;
  24. /**
  25. * Acceptable minute durations between time labels. These will be used to
  26. * computed the timeMarkerInterval of the TimeWindow when the start and end
  27. * times fit into these buckets.
  28. */
  29. const CLAMPED_MINUTE_RANGES = [
  30. 1,
  31. 5,
  32. 10,
  33. 20,
  34. 30,
  35. ONE_HOUR,
  36. ONE_HOUR * 2,
  37. ONE_HOUR * 4,
  38. ONE_HOUR * 8,
  39. ONE_HOUR * 12,
  40. ];
  41. /**
  42. * Compute the TimeWindowConfig given the timeline date boundaries and the width
  43. * of the timeline.
  44. */
  45. export function getConfigFromTimeRange(
  46. start: Date,
  47. end: Date,
  48. timelineWidth: number
  49. ): TimeWindowConfig {
  50. const elapsedMinutes = (end.getTime() - start.getTime()) / (1000 * 60);
  51. // Display only the time (no date) when the window is less than 24 hours
  52. const timeOnly = elapsedMinutes <= ONE_HOUR * 24;
  53. // When one pixel represents less than at least one minute we also want to
  54. // display second values on our labels.
  55. const displaySeconds = elapsedMinutes < timelineWidth;
  56. function computeMarkerInterval(pixels: number) {
  57. const minutesPerPixel = elapsedMinutes / timelineWidth;
  58. return minutesPerPixel * pixels;
  59. }
  60. // This is smallest minute value that we are willing to space our ticks
  61. const minMarkerWidth = timeOnly ? TIMELABEL_WIDTH_TIME : TIMELABEL_WIDTH_DATE;
  62. const minimumMarkerInterval = computeMarkerInterval(minMarkerWidth);
  63. const referenceMarkerInterval = computeMarkerInterval(TIMELABEL_WIDTH_FULL);
  64. const intervals = {referenceMarkerInterval, minimumMarkerInterval};
  65. for (const minutes of CLAMPED_MINUTE_RANGES) {
  66. if (minutes < minimumMarkerInterval) {
  67. continue;
  68. }
  69. return {
  70. start,
  71. end,
  72. elapsedMinutes,
  73. timelineWidth,
  74. intervals: {...intervals, normalMarkerInterval: minutes},
  75. dateTimeProps: {timeOnly},
  76. dateLabelFormat: getFormat({timeOnly, seconds: displaySeconds}),
  77. };
  78. }
  79. // Calculate the days in between each tick marker at the minimum time
  80. const normalMarkerInterval =
  81. Math.ceil(minimumMarkerInterval / (ONE_HOUR * 24)) * ONE_HOUR * 24;
  82. return {
  83. start,
  84. end,
  85. elapsedMinutes,
  86. timelineWidth,
  87. intervals: {...intervals, normalMarkerInterval},
  88. dateTimeProps: {dateOnly: true},
  89. dateLabelFormat: getFormat(),
  90. };
  91. }
  92. /**
  93. * Aligns the given date to the start of a unit (minute, hour, day) based on
  94. * the minuteInterval size. This will align to the right side of the boundary
  95. *
  96. * 01:53:43 (10m interval) => 01:54:00
  97. * 01:32:00 (2hr interval) => 02:00:00
  98. */
  99. export function alignDateToBoundary(date: moment.Moment, minuteInterval: number) {
  100. if (minuteInterval < 60) {
  101. return date.minute(date.minutes() - (date.minutes() % minuteInterval)).seconds(0);
  102. }
  103. if (minuteInterval < 60 * 24) {
  104. return date.startOf('hour');
  105. }
  106. return date.startOf('day');
  107. }