dates.tsx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import moment from 'moment';
  2. import {parseStatsPeriod} from 'sentry/components/organizations/pageFilters/parse';
  3. import ConfigStore from 'sentry/stores/configStore';
  4. import {DateString} from 'sentry/types';
  5. // TODO(billy): Move to TimeRangeSelector specific utils
  6. export const DEFAULT_DAY_START_TIME = '00:00:00';
  7. export const DEFAULT_DAY_END_TIME = '23:59:59';
  8. const DATE_FORMAT_NO_TIMEZONE = 'YYYY/MM/DD HH:mm:ss';
  9. function getParser(local: boolean = false): typeof moment | typeof moment.utc {
  10. return local ? moment : moment.utc;
  11. }
  12. /**
  13. * Checks if string is valid time. Only accepts 24 hour format.
  14. *
  15. * Chrome's time input will (at least for US locale), allow you to input 12
  16. * hour format with AM/PM but the raw value is in 24 hour.
  17. *
  18. * Safari does not do any validation so you could get a value of > 24 hours
  19. */
  20. export function isValidTime(str: string): boolean {
  21. return moment(str, 'HH:mm', true).isValid();
  22. }
  23. /**
  24. * Given a date object, format in datetime in UTC
  25. * given: Tue Oct 09 2018 00:00:00 GMT-0700 (Pacific Daylight Time)
  26. * returns: "2018-10-09T07:00:00.000"
  27. */
  28. export function getUtcDateString(dateObj: moment.MomentInput): string {
  29. return moment.utc(dateObj).format(moment.HTML5_FMT.DATETIME_LOCAL_SECONDS);
  30. }
  31. export function getFormattedDate(
  32. dateObj: moment.MomentInput,
  33. format: string,
  34. {local}: {local?: boolean} = {}
  35. ): string {
  36. return getParser(local)(dateObj).format(format);
  37. }
  38. /**
  39. * Returns user timezone from their account preferences
  40. */
  41. export function getUserTimezone(): string {
  42. const user = ConfigStore.get('user');
  43. return user && user.options && user.options.timezone;
  44. }
  45. /**
  46. * Given a UTC date, return a Date object in local time
  47. */
  48. export function getUtcToLocalDateObject(date: moment.MomentInput): Date {
  49. return moment.utc(date).local().toDate();
  50. }
  51. /**
  52. * Sets time (hours + minutes) of the current date object
  53. *
  54. * @param {String} timeStr Time in 24hr format (HH:mm)
  55. */
  56. export function setDateToTime(
  57. dateObj: string | Date,
  58. timeStr: string,
  59. {local}: {local?: boolean} = {}
  60. ): Date {
  61. const [hours, minutes, seconds] = timeStr.split(':').map(t => parseInt(t, 10));
  62. const date = new Date(+dateObj);
  63. if (local) {
  64. date.setHours(hours, minutes);
  65. } else {
  66. date.setUTCHours(hours, minutes);
  67. }
  68. if (typeof seconds !== 'undefined') {
  69. date.setSeconds(seconds);
  70. }
  71. return date;
  72. }
  73. /**
  74. * Given a UTC timestamp, return a system date object with the same date
  75. * e.g. given: system is -0700 (PST),
  76. * 1/1/2001 @ 22:00 UTC, return: 1/1/2001 @ 22:00 -0700 (PST)
  77. */
  78. export function getUtcToSystem(dateObj: moment.MomentInput): Date {
  79. // This is required because if your system timezone !== user configured timezone
  80. // then there will be a mismatch of dates with `react-date-picker`
  81. //
  82. // We purposely strip the timezone when formatting from the utc timezone
  83. return new Date(moment.utc(dateObj).format(DATE_FORMAT_NO_TIMEZONE));
  84. }
  85. /**
  86. * Given a timestamp, format to user preference timezone, and strip timezone to
  87. * return a system date object with the same date
  88. *
  89. * e.g. given: system is -0700 (PST) and user preference is -0400 (EST),
  90. * 1/1/2001 @ 22:00 UTC --> 1/1/2001 @ 18:00 -0400 (EST) -->
  91. * return: 1/1/2001 @ 18:00 -0700 (PST)
  92. */
  93. export function getLocalToSystem(dateObj: moment.MomentInput): Date {
  94. // This is required because if your system timezone !== user configured timezone
  95. // then there will be a mismatch of dates with `react-date-picker`
  96. //
  97. // We purposely strip the timezone when formatting from the utc timezone
  98. return new Date(moment(dateObj).format(DATE_FORMAT_NO_TIMEZONE));
  99. }
  100. // Get the beginning of day (e.g. midnight)
  101. export function getStartOfDay(date: moment.MomentInput): Date {
  102. return moment(date)
  103. .startOf('day')
  104. .startOf('hour')
  105. .startOf('minute')
  106. .startOf('second')
  107. .local()
  108. .toDate();
  109. }
  110. // Get tomorrow at midnight so that default endtime
  111. // is inclusive of today
  112. export function getEndOfDay(date: moment.MomentInput): Date {
  113. return moment(date)
  114. .add(1, 'day')
  115. .startOf('hour')
  116. .startOf('minute')
  117. .startOf('second')
  118. .subtract(1, 'second')
  119. .local()
  120. .toDate();
  121. }
  122. export function getPeriodAgo(
  123. period: moment.unitOfTime.DurationConstructor,
  124. unit: number
  125. ): moment.Moment {
  126. return moment().local().subtract(unit, period);
  127. }
  128. // Get the start of the day (midnight) for a period ago
  129. //
  130. // e.g. 2 weeks ago at midnight
  131. export function getStartOfPeriodAgo(
  132. period: moment.unitOfTime.DurationConstructor,
  133. unit: number
  134. ): Date {
  135. return getStartOfDay(getPeriodAgo(period, unit));
  136. }
  137. /**
  138. * Convert an interval string into a number of seconds.
  139. * This allows us to create end timestamps from starting ones
  140. * enabling us to find events in narrow windows.
  141. *
  142. * @param {String} interval The interval to convert.
  143. * @return {Integer}
  144. */
  145. export function intervalToMilliseconds(interval: string): number {
  146. const pattern = /^(\d+)(d|h|m)$/;
  147. const matches = pattern.exec(interval);
  148. if (!matches) {
  149. return 0;
  150. }
  151. const [, value, unit] = matches;
  152. const multipliers = {
  153. d: 60 * 60 * 24,
  154. h: 60 * 60,
  155. m: 60,
  156. };
  157. return parseInt(value, 10) * multipliers[unit] * 1000;
  158. }
  159. /**
  160. * This parses our period shorthand strings (e.g. <int><unit>)
  161. * and converts it into hours
  162. */
  163. export function parsePeriodToHours(str: string): number {
  164. const result = parseStatsPeriod(str);
  165. if (!result) {
  166. return -1;
  167. }
  168. const {period, periodLength} = result;
  169. const periodNumber = parseInt(period, 10);
  170. switch (periodLength) {
  171. case 's':
  172. return periodNumber / (60 * 60);
  173. case 'm':
  174. return periodNumber / 60;
  175. case 'h':
  176. return periodNumber;
  177. case 'd':
  178. return periodNumber * 24;
  179. case 'w':
  180. return periodNumber * 24 * 7;
  181. default:
  182. return -1;
  183. }
  184. }
  185. export function statsPeriodToDays(
  186. statsPeriod?: string | null,
  187. start?: DateString,
  188. end?: DateString
  189. ) {
  190. if (statsPeriod && statsPeriod.endsWith('d')) {
  191. return parseInt(statsPeriod.slice(0, -1), 10);
  192. }
  193. if (statsPeriod && statsPeriod.endsWith('h')) {
  194. return parseInt(statsPeriod.slice(0, -1), 10) / 24;
  195. }
  196. if (start && end) {
  197. return (new Date(end).getTime() - new Date(start).getTime()) / (24 * 60 * 60 * 1000);
  198. }
  199. return 0;
  200. }
  201. export const use24Hours = () => ConfigStore.get('user')?.options?.clock24Hours;
  202. export function getTimeFormat({displaySeconds = false}: {displaySeconds?: boolean} = {}) {
  203. if (use24Hours()) {
  204. return displaySeconds ? 'HH:mm:ss' : 'HH:mm';
  205. }
  206. return displaySeconds ? 'LTS' : 'LT';
  207. }
  208. export function getInternalDate(date: string | Date, utc?: boolean | null) {
  209. if (utc) {
  210. return getUtcToSystem(date);
  211. }
  212. return new Date(
  213. moment.tz(moment.utc(date), getUserTimezone()).format('YYYY/MM/DD HH:mm:ss')
  214. );
  215. }
  216. /**
  217. * Strips timezone from local date, creates a new moment date object with timezone
  218. * returns the moment as a Date object
  219. */
  220. export function getDateWithTimezoneInUtc(date?: Date, utc?: boolean | null) {
  221. return moment
  222. .tz(
  223. moment(date).local().format('YYYY-MM-DD HH:mm:ss'),
  224. utc ? 'UTC' : getUserTimezone()
  225. )
  226. .utc()
  227. .toDate();
  228. }