daterange-utils.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Date range utils
  2. export function subtract(oldDate, nDays) {
  3. var newDate = new Date(oldDate)
  4. newDate.setDate(newDate.getDate() - nDays);
  5. return newDate;
  6. }
  7. export function thisMonth(oldDate) {
  8. var d1 = new Date(oldDate)
  9. d1.setDate(1);
  10. var d2 = new Date(d1.getFullYear(), d1.getMonth() + 1, 0);
  11. return [d1, d2];
  12. };
  13. export function lastNMonths(oldDate, nMonths) {
  14. var d0 = new Date(oldDate)
  15. var d1 = new Date(d0.getFullYear(), d0.getMonth() - nMonths + 2, 0);
  16. d1.setDate(1);
  17. var d2 = new Date(d0.getFullYear(), d0.getMonth() + 1, 0);
  18. return [d1, d2];
  19. };
  20. export function getOffsetBetweenTimezonesForDate(date, timezone1, timezone2) {
  21. const o1 = getTimeZoneOffset(date, timezone1)
  22. const o2 = getTimeZoneOffset(date, timezone2)
  23. return o2 - o1
  24. }
  25. function getTimeZoneOffset(date, timeZone) {
  26. // Abuse the Intl API to get a local ISO 8601 string for a given time zone.
  27. let iso = date.toLocaleString('en-CA', { timeZone, hour12: false }).replace(', ', 'T');
  28. // Include the milliseconds from the original timestamp
  29. iso += '.' + date.getMilliseconds().toString().padStart(3, '0');
  30. // Lie to the Date object constructor that it's a UTC time.
  31. const lie = new Date(iso + 'Z');
  32. // Return the difference in timestamps, as minutes
  33. // Positive values are West of GMT, opposite of ISO 8601
  34. // this matches the output of `Date.getTimeZoneOffset`
  35. return -(lie - date) / 60 / 1000;
  36. }
  37. /**
  38. * Count the number of Daylight Saving Time (DST) transitions within a given datetime range.
  39. * @param {Date} startDate - The start date of the datetime range.
  40. * @param {Date} endDate - The end date of the datetime range.
  41. * @param {number} increment - The number of days to increment between iterations.
  42. * @returns {number} The count of DST transitions within the specified range.
  43. */
  44. export function countDSTTransitions(startDate, endDate, increment) {
  45. let transitions = 0;
  46. let currentDate = new Date(startDate);
  47. let nextDate = new Date(startDate);
  48. while (currentDate <= endDate) {
  49. const currentOffset = currentDate.getTimezoneOffset();
  50. nextDate.setDate(currentDate.getDate() + increment);
  51. if (nextDate > endDate) {
  52. nextDate = endDate;
  53. }
  54. const nextOffset = nextDate.getTimezoneOffset();
  55. if (currentOffset !== nextOffset) {
  56. transitions++;
  57. }
  58. currentDate.setDate(currentDate.getDate() + increment);
  59. }
  60. return transitions;
  61. }