getConfigFromTimeRange.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import {getFormat} from 'sentry/utils/dates';
  2. import type {TimeWindowConfig} from '../types';
  3. /**
  4. * The minimum pixels to allocate to the reference start time label which
  5. * always includes date, time, and timezone.
  6. */
  7. const TIMELABEL_WIDTH_FULL = 115;
  8. /**
  9. * The minimum pixels to allocate to each time label when it is a full date.
  10. */
  11. const TIMELABEL_WIDTH_DATE = 110;
  12. /**
  13. * The minimum pixels to allocate to each time label when it's a timestaamp.
  14. */
  15. const TIMELABEL_WIDTH_TIME = 100;
  16. const ONE_HOUR = 60;
  17. /**
  18. * Acceptable minute durations between time labels. These will be used to
  19. * computed the timeMarkerInterval of the TimeWindow when the start and end
  20. * times fit into these buckets.
  21. */
  22. const CLAMPED_MINUTE_RANGES = [
  23. 1,
  24. 5,
  25. 10,
  26. 20,
  27. 30,
  28. ONE_HOUR,
  29. ONE_HOUR * 2,
  30. ONE_HOUR * 4,
  31. ONE_HOUR * 8,
  32. ONE_HOUR * 12,
  33. ];
  34. /**
  35. * Compute the TimeWindowConfig given the timeline date boundaries and the width
  36. * of the timeline.
  37. */
  38. export function getConfigFromTimeRange(
  39. start: Date,
  40. end: Date,
  41. timelineWidth: number
  42. ): TimeWindowConfig {
  43. const elapsedMinutes = (end.getTime() - start.getTime()) / (1000 * 60);
  44. // Display only the time (no date) when the start and end times are the same day
  45. const timeOnly = elapsedMinutes <= ONE_HOUR * 24 && start.getDate() === end.getDate();
  46. // When one pixel represents less than at least one minute we also want to
  47. // display second values on our labels.
  48. const displaySeconds = elapsedMinutes < timelineWidth;
  49. function computeMarkerInterval(pixels: number) {
  50. const minutesPerPixel = elapsedMinutes / timelineWidth;
  51. return minutesPerPixel * pixels;
  52. }
  53. // This is smallest minute value that we are willing to space our ticks
  54. const minMarkerWidth = timeOnly ? TIMELABEL_WIDTH_TIME : TIMELABEL_WIDTH_DATE;
  55. const minimumMarkerInterval = computeMarkerInterval(minMarkerWidth);
  56. const referenceMarkerInterval = computeMarkerInterval(TIMELABEL_WIDTH_FULL);
  57. const intervals = {referenceMarkerInterval, minimumMarkerInterval};
  58. for (const minutes of CLAMPED_MINUTE_RANGES) {
  59. if (minutes < minimumMarkerInterval) {
  60. continue;
  61. }
  62. return {
  63. start,
  64. end,
  65. elapsedMinutes,
  66. timelineWidth,
  67. intervals: {...intervals, normalMarkerInterval: minutes},
  68. dateTimeProps: {timeOnly},
  69. dateLabelFormat: getFormat({timeOnly, seconds: displaySeconds}),
  70. };
  71. }
  72. // Calculate the days in between each tick marker at the minimum time
  73. const normalMarkerInterval =
  74. Math.ceil(minimumMarkerInterval / (ONE_HOUR * 24)) * ONE_HOUR * 24;
  75. return {
  76. start,
  77. end,
  78. elapsedMinutes,
  79. timelineWidth,
  80. intervals: {...intervals, normalMarkerInterval},
  81. dateTimeProps: {dateOnly: true},
  82. dateLabelFormat: getFormat(),
  83. };
  84. }