time.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*!
  2. * All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
  4. * v1.0.0-beta.82
  5. */
  6. import { isValidNumber } from "./number";
  7. export const maxTenthForMinuteAndSecond = 5;
  8. function createLocaleDateTimeFormatter(locale, includeSeconds = true) {
  9. try {
  10. const options = {
  11. hour: "2-digit",
  12. minute: "2-digit",
  13. timeZone: "UTC"
  14. };
  15. if (includeSeconds) {
  16. options.second = "2-digit";
  17. }
  18. return new Intl.DateTimeFormat(locale, options);
  19. }
  20. catch (e) {
  21. throw new Error(`Invalid locale supplied while attempting to create a DateTime formatter: ${locale}`);
  22. }
  23. }
  24. export function formatTimePart(number) {
  25. const numberAsString = number.toString();
  26. return number >= 0 && number <= 9 ? numberAsString.padStart(2, "0") : numberAsString;
  27. }
  28. export function formatTimeString(value) {
  29. if (!isValidTime(value)) {
  30. return null;
  31. }
  32. const [hourString, minuteString, secondString] = value.split(":");
  33. const hour = formatTimePart(parseInt(hourString));
  34. const minute = formatTimePart(parseInt(minuteString));
  35. if (secondString) {
  36. const second = formatTimePart(parseInt(secondString));
  37. return `${hour}:${minute}:${second}`;
  38. }
  39. return `${hour}:${minute}`;
  40. }
  41. export function getLocaleHourCycle(locale) {
  42. const formatter = createLocaleDateTimeFormatter(locale);
  43. const parts = formatter.formatToParts(new Date(Date.UTC(0, 0, 0, 0, 0, 0)));
  44. return getLocalizedTimePart("meridiem", parts) ? "12" : "24";
  45. }
  46. function getLocalizedTimePart(part, parts) {
  47. var _a, _b, _c, _d;
  48. if (!part || !parts) {
  49. return null;
  50. }
  51. if (part === "hourSuffix") {
  52. const hourIndex = parts.indexOf(parts.find(({ type }) => type === "hour"));
  53. const minuteIndex = parts.indexOf(parts.find(({ type }) => type === "minute"));
  54. const hourSuffix = parts[hourIndex + 1];
  55. return hourSuffix && hourSuffix.type === "literal" && minuteIndex - hourIndex === 2
  56. ? ((_a = hourSuffix.value) === null || _a === void 0 ? void 0 : _a.trim()) || null
  57. : null;
  58. }
  59. if (part === "minuteSuffix") {
  60. const minuteIndex = parts.indexOf(parts.find(({ type }) => type === "minute"));
  61. const secondIndex = parts.indexOf(parts.find(({ type }) => type === "second"));
  62. const minuteSuffix = parts[minuteIndex + 1];
  63. return minuteSuffix && minuteSuffix.type === "literal" && secondIndex - minuteIndex === 2
  64. ? ((_b = minuteSuffix.value) === null || _b === void 0 ? void 0 : _b.trim()) || null
  65. : null;
  66. }
  67. if (part === "secondSuffix") {
  68. const secondIndex = parts.indexOf(parts.find(({ type }) => type === "second"));
  69. const secondSuffix = parts[secondIndex + 1];
  70. return secondSuffix && secondSuffix.type === "literal" ? ((_c = secondSuffix.value) === null || _c === void 0 ? void 0 : _c.trim()) || null : null;
  71. }
  72. return ((_d = parts.find(({ type }) => (part == "meridiem" ? type === "dayPeriod" : type === part))) === null || _d === void 0 ? void 0 : _d.value) || null;
  73. }
  74. export function getMeridiem(hour) {
  75. if (!isValidNumber(hour)) {
  76. return null;
  77. }
  78. const hourAsNumber = parseInt(hour);
  79. return hourAsNumber >= 0 && hourAsNumber <= 11 ? "AM" : "PM";
  80. }
  81. export function isValidTime(value) {
  82. if (!value || value.startsWith(":") || value.endsWith(":")) {
  83. return false;
  84. }
  85. const splitValue = value.split(":");
  86. const validLength = splitValue.length > 1 && splitValue.length < 4;
  87. if (!validLength) {
  88. return false;
  89. }
  90. const [hour, minute, second] = splitValue;
  91. const hourAsNumber = parseInt(splitValue[0]);
  92. const minuteAsNumber = parseInt(splitValue[1]);
  93. const secondAsNumber = parseInt(splitValue[2]);
  94. const hourValid = isValidNumber(hour) && hourAsNumber >= 0 && hourAsNumber < 24;
  95. const minuteValid = isValidNumber(minute) && minuteAsNumber >= 0 && minuteAsNumber < 60;
  96. const secondValid = isValidNumber(second) && secondAsNumber >= 0 && secondAsNumber < 60;
  97. if ((hourValid && minuteValid && !second) || (hourValid && minuteValid && secondValid)) {
  98. return true;
  99. }
  100. }
  101. function isValidTimePart(value, part) {
  102. if (part === "meridiem") {
  103. return value === "AM" || value === "PM";
  104. }
  105. if (!isValidNumber(value)) {
  106. return false;
  107. }
  108. const valueAsNumber = Number(value);
  109. return part === "hour" ? valueAsNumber >= 0 && valueAsNumber < 24 : valueAsNumber >= 0 && valueAsNumber < 60;
  110. }
  111. export function localizeTimePart(value, part, locale) {
  112. if (!isValidTimePart(value, part)) {
  113. return;
  114. }
  115. const valueAsNumber = parseInt(value);
  116. const date = new Date(Date.UTC(0, 0, 0, part === "hour" ? valueAsNumber : part === "meridiem" ? (value === "AM" ? 0 : 12) : 0, part === "minute" ? valueAsNumber : 0, part === "second" ? valueAsNumber : 0));
  117. if (!date) {
  118. return;
  119. }
  120. const formatter = createLocaleDateTimeFormatter(locale);
  121. const parts = formatter.formatToParts(date);
  122. return getLocalizedTimePart(part, parts);
  123. }
  124. export function localizeTimeString(value, locale = "en", includeSeconds = true) {
  125. if (!isValidTime(value)) {
  126. return null;
  127. }
  128. const { hour, minute, second = "0" } = parseTimeString(value);
  129. const dateFromTimeString = new Date(Date.UTC(0, 0, 0, parseInt(hour), parseInt(minute), parseInt(second)));
  130. const formatter = createLocaleDateTimeFormatter(locale, includeSeconds);
  131. return (formatter === null || formatter === void 0 ? void 0 : formatter.format(dateFromTimeString)) || null;
  132. }
  133. export function localizeTimeStringToParts(value, locale = "en") {
  134. if (!isValidTime(value)) {
  135. return null;
  136. }
  137. const { hour, minute, second = "0" } = parseTimeString(value);
  138. const dateFromTimeString = new Date(Date.UTC(0, 0, 0, parseInt(hour), parseInt(minute), parseInt(second)));
  139. if (dateFromTimeString) {
  140. const formatter = createLocaleDateTimeFormatter(locale);
  141. const parts = formatter.formatToParts(dateFromTimeString);
  142. return {
  143. localizedHour: getLocalizedTimePart("hour", parts),
  144. localizedHourSuffix: getLocalizedTimePart("hourSuffix", parts),
  145. localizedMinute: getLocalizedTimePart("minute", parts),
  146. localizedMinuteSuffix: getLocalizedTimePart("minuteSuffix", parts),
  147. localizedSecond: getLocalizedTimePart("second", parts),
  148. localizedSecondSuffix: getLocalizedTimePart("secondSuffix", parts),
  149. localizedMeridiem: getLocalizedTimePart("meridiem", parts)
  150. };
  151. }
  152. return null;
  153. }
  154. export function getTimeParts(value, locale = "en") {
  155. if (!isValidTime(value)) {
  156. return null;
  157. }
  158. const { hour, minute, second = "0" } = parseTimeString(value);
  159. const dateFromTimeString = new Date(Date.UTC(0, 0, 0, parseInt(hour), parseInt(minute), parseInt(second)));
  160. if (dateFromTimeString) {
  161. const formatter = createLocaleDateTimeFormatter(locale);
  162. const parts = formatter.formatToParts(dateFromTimeString);
  163. return parts;
  164. }
  165. return null;
  166. }
  167. export function parseTimeString(value) {
  168. if (isValidTime(value)) {
  169. const [hour, minute, second] = value.split(":");
  170. return {
  171. hour,
  172. minute,
  173. second
  174. };
  175. }
  176. return {
  177. hour: null,
  178. minute: null,
  179. second: null
  180. };
  181. }