date.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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.97
  5. */
  6. import { numberStringFormatter } from "./locale";
  7. /**
  8. * Check if date is within a min and max
  9. *
  10. * @param date
  11. * @param min
  12. * @param max
  13. */
  14. export function inRange(date, min, max) {
  15. const time = date.getTime();
  16. const afterMin = !(min instanceof Date) || time >= min.getTime();
  17. const beforeMax = !(max instanceof Date) || time <= max.getTime();
  18. return afterMin && beforeMax;
  19. }
  20. /**
  21. * Ensures date is within range,
  22. * returns min or max if out of bounds
  23. *
  24. * @param date
  25. * @param min
  26. * @param max
  27. */
  28. export function dateFromRange(date, min, max) {
  29. if (!(date instanceof Date)) {
  30. return null;
  31. }
  32. const time = date.getTime();
  33. const beforeMin = min instanceof Date && time < min.getTime();
  34. const afterMax = max instanceof Date && time > max.getTime();
  35. if (beforeMin) {
  36. return min;
  37. }
  38. if (afterMax) {
  39. return max;
  40. }
  41. return date;
  42. }
  43. /**
  44. * Parse an iso8601 string (YYYY-mm-dd) into a valid date.
  45. * TODO: handle time when time of day UI is added
  46. *
  47. * @param iso8601
  48. * @param isEndDate
  49. */
  50. export function dateFromISO(iso8601, isEndDate = false) {
  51. if (iso8601 instanceof Date) {
  52. return iso8601;
  53. }
  54. if (!iso8601 || typeof iso8601 !== "string") {
  55. return null;
  56. }
  57. const d = iso8601.split(/[: T-]/).map(parseFloat);
  58. const date = new Date(d[0], (d[1] || 1) - 1, d[2] || 1);
  59. date.setFullYear(d[0]);
  60. if (isNaN(date.getTime())) {
  61. throw new Error(`Invalid ISO 8601 date: "${iso8601}"`);
  62. }
  63. if (isEndDate) {
  64. return setEndOfDay(date);
  65. }
  66. return date;
  67. }
  68. /**
  69. * Return first portion of ISO string (YYYY-mm-dd)
  70. *
  71. * @param date
  72. */
  73. export function dateToISO(date) {
  74. if (typeof date === "string") {
  75. return date;
  76. }
  77. if (date instanceof Date) {
  78. return new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().split("T")[0];
  79. }
  80. return "";
  81. }
  82. /**
  83. * Check if two dates are the same day, month, year
  84. *
  85. * @param d1
  86. * @param d2
  87. */
  88. export function sameDate(d1, d2) {
  89. return (d1 instanceof Date &&
  90. d2 instanceof Date &&
  91. d1.getDate() === d2.getDate() &&
  92. d1.getMonth() === d2.getMonth() &&
  93. d1.getFullYear() === d2.getFullYear());
  94. }
  95. /**
  96. * Get a date one month in the past
  97. *
  98. * @param date
  99. */
  100. export function prevMonth(date) {
  101. const month = date.getMonth();
  102. const nextDate = new Date(date);
  103. nextDate.setMonth(month - 1);
  104. // date doesn't exist in new month, use last day
  105. if (month === nextDate.getMonth()) {
  106. return new Date(date.getFullYear(), month, 0);
  107. }
  108. return nextDate;
  109. }
  110. /**
  111. * Get a date one month in the future
  112. *
  113. * @param date
  114. */
  115. export function nextMonth(date) {
  116. const month = date.getMonth();
  117. const nextDate = new Date(date);
  118. nextDate.setMonth(month + 1);
  119. // date doesn't exist in new month, use last day
  120. if ((month + 2) % 7 === nextDate.getMonth() % 7) {
  121. return new Date(date.getFullYear(), month + 2, 0);
  122. }
  123. return nextDate;
  124. }
  125. /**
  126. * Parse numeric units for day, month, and year from a localized string
  127. * month starts at 0 (can pass to date constructor)
  128. *
  129. * @param str
  130. * @param localeData
  131. */
  132. export function parseDateString(str, localeData) {
  133. const { separator, unitOrder } = localeData;
  134. const order = getOrder(unitOrder);
  135. const values = str.split(separator).map((part) => numberStringFormatter.delocalize(part));
  136. return {
  137. day: parseInt(values[order.indexOf("d")]),
  138. month: parseInt(values[order.indexOf("m")]) - 1,
  139. year: parseInt(values[order.indexOf("y")])
  140. };
  141. }
  142. /**
  143. * Based on the unitOrder string, find order of month, day, and year for locale
  144. *
  145. * @param unitOrder
  146. */
  147. export function getOrder(unitOrder) {
  148. const signifiers = ["d", "m", "y"];
  149. const order = unitOrder.toLowerCase();
  150. return signifiers.sort((a, b) => order.indexOf(a) - order.indexOf(b));
  151. }
  152. /**
  153. * Get number of days between two dates
  154. *
  155. * @param date1
  156. * @param date2
  157. */
  158. export function getDaysDiff(date1, date2) {
  159. const ts1 = date1.getTime();
  160. const ts2 = date2.getTime();
  161. return (ts1 - ts2) / (1000 * 3600 * 24);
  162. }
  163. /**
  164. * Set time of the day to the end.
  165. *
  166. * @param {Date} date Date.
  167. * @returns {Date} Date with time set to end of day .
  168. */
  169. export function setEndOfDay(date) {
  170. date.setHours(23, 59, 59, 999);
  171. return date;
  172. }