dateTime.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import moment from 'moment';
  2. import momentTimezone from 'moment-timezone';
  3. import ConfigStore from 'sentry/stores/configStore';
  4. interface Props extends React.HTMLAttributes<HTMLTimeElement> {
  5. /**
  6. * Input date.
  7. */
  8. date: moment.MomentInput | momentTimezone.MomentInput;
  9. /**
  10. * If true, will only return the date part, e.g. "Jan 1".
  11. */
  12. dateOnly?: boolean;
  13. /**
  14. * Formatting string. If specified, this formatting string will override all
  15. * other formatting props (dateOnly, timeOnly, year).
  16. */
  17. format?: string;
  18. /**
  19. * Whether to show the seconds. Is false by default.
  20. */
  21. seconds?: boolean;
  22. /**
  23. * If true, will only return the time part, e.g. "2:50 PM"
  24. */
  25. timeOnly?: boolean;
  26. /**
  27. * Whether to show the time zone. If not specified, the returned date string
  28. * will not contain the time zone _unless_ the time is UTC, in which case
  29. * the user would want to know that it's UTC and not their own time zone.
  30. */
  31. timeZone?: boolean;
  32. /**
  33. * Whether the date input is UTC time or not.
  34. */
  35. utc?: boolean;
  36. /**
  37. * Whether to show the year. If not specified, the returned date string will
  38. * not contain the year _if_ the date is not in the current calendar year.
  39. * For example: "Feb 1" (2022), "Jan 1" (2022), "Dec 31, 2021".
  40. */
  41. year?: boolean;
  42. }
  43. function getDateFormat({year}: Pick<Props, 'year'>) {
  44. // "Jan 1, 2022" or "Jan 1"
  45. return year ? 'MMM D, YYYY' : 'MMM D';
  46. }
  47. function getTimeFormat({clock24Hours, seconds, timeZone}) {
  48. const substrings = [
  49. clock24Hours ? 'HH' : 'h', // hour – "23" (24h format) or "11" (12h format)
  50. ':mm', // minute
  51. seconds ? ':ss' : '', // second
  52. clock24Hours ? '' : ' A', // AM/PM
  53. timeZone ? ' z' : '', // time zone
  54. ];
  55. return substrings.join('');
  56. }
  57. function getFormat({
  58. dateOnly,
  59. timeOnly,
  60. year,
  61. seconds,
  62. timeZone,
  63. clock24Hours,
  64. }: Pick<Props, 'dateOnly' | 'timeOnly' | 'year' | 'seconds' | 'timeZone'> & {
  65. clock24Hours: boolean;
  66. }) {
  67. if (dateOnly) {
  68. return getDateFormat({year});
  69. }
  70. if (timeOnly) {
  71. return getTimeFormat({clock24Hours, seconds, timeZone});
  72. }
  73. const dateFormat = getDateFormat({year});
  74. const timeFormat = getTimeFormat({
  75. clock24Hours,
  76. seconds,
  77. timeZone,
  78. });
  79. // If the year is shown, then there's already a comma in dateFormat ("Jan 1, 2020"),
  80. // so we don't need to add another comma between the date and time
  81. return year ? `${dateFormat} ${timeFormat}` : `${dateFormat}, ${timeFormat}`;
  82. }
  83. function DateTime({
  84. format,
  85. date,
  86. utc,
  87. dateOnly,
  88. timeOnly,
  89. year,
  90. timeZone,
  91. seconds = false,
  92. ...props
  93. }: Props) {
  94. const user = ConfigStore.get('user');
  95. const options = user?.options;
  96. const formatString =
  97. format ??
  98. getFormat({
  99. dateOnly,
  100. timeOnly,
  101. // If the year prop is defined, then use it. Otherwise only show the year if `date`
  102. // is in the current year.
  103. year: year ?? moment().year() !== moment(date).year(),
  104. // If timeZone is defined, use it. Otherwise only show the time zone if we're using
  105. // UTC time.
  106. timeZone: timeZone ?? utc,
  107. seconds,
  108. ...options,
  109. });
  110. return (
  111. <time {...props}>
  112. {utc
  113. ? moment.utc(date as moment.MomentInput).format(formatString)
  114. : momentTimezone.tz(date, options?.timezone ?? '').format(formatString)}
  115. </time>
  116. );
  117. }
  118. export default DateTime;