Commit 772ee696 authored by Nathan Friend's avatar Nathan Friend Committed by Jose Ivan Vargas

Add UTC support to date add/subtract utilities

This commit update all date addition/subtraction utilities to optionally
support perfoming the calculation with UTC dates, which ignores
Daylight Saving Time.
parent b1a936ba
...@@ -676,69 +676,127 @@ export const secondsToHours = (offset) => { ...@@ -676,69 +676,127 @@ export const secondsToHours = (offset) => {
}; };
/** /**
* Returns the date n days after the date provided * Returns the date `n` days after the date provided
* *
* @param {Date} date the initial date * @param {Date} date the initial date
* @param {Number} numberOfDays number of days after * @param {Number} numberOfDays number of days after
* @return {Date} the date following the date provided * @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC dates.
* This will cause Daylight Saving Time to be ignored. Defaults to `false`
* if not provided, which causes the calculation to be performed in the
* user's timezone.
*
* @return {Date} A `Date` object `n` days after the provided `Date`
*/ */
export const nDaysAfter = (date, numberOfDays) => export const nDaysAfter = (date, numberOfDays, { utc = false } = {}) => {
new Date(newDate(date)).setDate(date.getDate() + numberOfDays); const clone = newDate(date);
const cloneValue = utc
? clone.setUTCDate(date.getUTCDate() + numberOfDays)
: clone.setDate(date.getDate() + numberOfDays);
return new Date(cloneValue);
};
/** /**
* Returns the date n days before the date provided * Returns the date `n` days before the date provided
* *
* @param {Date} date the initial date * @param {Date} date the initial date
* @param {Number} numberOfDays number of days before * @param {Number} numberOfDays number of days before
* @return {Date} the date preceding the date provided * @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC dates.
* This will cause Daylight Saving Time to be ignored. Defaults to `false`
* if not provided, which causes the calculation to be performed in the
* user's timezone.
* @return {Date} A `Date` object `n` days before the provided `Date`
*/ */
export const nDaysBefore = (date, numberOfDays) => nDaysAfter(date, -numberOfDays); export const nDaysBefore = (date, numberOfDays, options) =>
nDaysAfter(date, -numberOfDays, options);
/** /**
* Returns the date n weeks after the date provided * Returns the date `n` weeks after the date provided
* *
* @param {Date} date the initial date * @param {Date} date the initial date
* @param {Number} numberOfWeeks number of weeks after * @param {Number} numberOfWeeks number of weeks after
* @return {Date} the date following the date provided * @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC dates.
* This will cause Daylight Saving Time to be ignored. Defaults to `false`
* if not provided, which causes the calculation to be performed in the
* user's timezone.
*
* @return {Date} A `Date` object `n` weeks after the provided `Date`
*/ */
export const nWeeksAfter = (date, numberOfWeeks) => export const nWeeksAfter = (date, numberOfWeeks, options) =>
new Date(newDate(date)).setDate(date.getDate() + DAYS_IN_WEEK * numberOfWeeks); nDaysAfter(date, DAYS_IN_WEEK * numberOfWeeks, options);
/** /**
* Returns the date n weeks before the date provided * Returns the date `n` weeks before the date provided
* *
* @param {Date} date the initial date * @param {Date} date the initial date
* @param {Number} numberOfWeeks number of weeks before * @param {Number} numberOfWeeks number of weeks before
* @return {Date} the date following the date provided * @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC dates.
* This will cause Daylight Saving Time to be ignored. Defaults to `false`
* if not provided, which causes the calculation to be performed in the
* user's timezone.
*
* @return {Date} A `Date` object `n` weeks before the provided `Date`
*/ */
export const nWeeksBefore = (date, numberOfWeeks) => nWeeksAfter(date, -numberOfWeeks); export const nWeeksBefore = (date, numberOfWeeks, options) =>
nWeeksAfter(date, -numberOfWeeks, options);
/** /**
* Returns the date n months after the date provided * Returns the date `n` months after the date provided
* *
* @param {Date} date the initial date * @param {Date} date the initial date
* @param {Number} numberOfMonths number of months after * @param {Number} numberOfMonths number of months after
* @return {Date} the date following the date provided * @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC dates.
* This will cause Daylight Saving Time to be ignored. Defaults to `false`
* if not provided, which causes the calculation to be performed in the
* user's timezone.
*
* @return {Date} A `Date` object `n` months after the provided `Date`
*/ */
export const nMonthsAfter = (date, numberOfMonths) => export const nMonthsAfter = (date, numberOfMonths, { utc = false } = {}) => {
new Date(newDate(date)).setMonth(date.getMonth() + numberOfMonths); const clone = newDate(date);
const cloneValue = utc
? clone.setUTCMonth(date.getUTCMonth() + numberOfMonths)
: clone.setMonth(date.getMonth() + numberOfMonths);
return new Date(cloneValue);
};
/** /**
* Returns the date n months before the date provided * Returns the date `n` months before the date provided
* *
* @param {Date} date the initial date * @param {Date} date the initial date
* @param {Number} numberOfMonths number of months before * @param {Number} numberOfMonths number of months before
* @return {Date} the date preceding the date provided * @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC dates.
* This will cause Daylight Saving Time to be ignored. Defaults to `false`
* if not provided, which causes the calculation to be performed in the
* user's timezone.
*
* @return {Date} A `Date` object `n` months before the provided `Date`
*/ */
export const nMonthsBefore = (date, numberOfMonths) => nMonthsAfter(date, -numberOfMonths); export const nMonthsBefore = (date, numberOfMonths, options) =>
nMonthsAfter(date, -numberOfMonths, options);
/** /**
* Returns the date after the date provided * Returns the date after the date provided
* *
* @param {Date} date the initial date * @param {Date} date the initial date
* @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC dates.
* This will cause Daylight Saving Time to be ignored. Defaults to `false`
* if not provided, which causes the calculation to be performed in the
* user's timezone.
*
* @return {Date} the date following the date provided * @return {Date} the date following the date provided
*/ */
export const dayAfter = (date) => new Date(newDate(date).setDate(date.getDate() + 1)); export const dayAfter = (date, options) => nDaysAfter(date, 1, options);
/** /**
* Mimics the behaviour of the rails distance_of_time_in_words function * Mimics the behaviour of the rails distance_of_time_in_words function
...@@ -933,3 +991,22 @@ export const isToday = (date) => { ...@@ -933,3 +991,22 @@ export const isToday = (date) => {
date.getFullYear() === today.getFullYear() date.getFullYear() === today.getFullYear()
); );
}; };
/**
* Returns the start of the provided day
*
* @param {Object} [options={}] Additional options for this calculation
* @param {boolean} [options.utc=false] Perform the calculation using UTC time.
* If `true`, the time returned will be midnight UTC. If `false` (the default)
* the time returned will be midnight in the user's local time.
*
* @returns {Date} A new `Date` object that represents the start of the day
* of the provided date
*/
export const getStartOfDay = (date, { utc = false } = {}) => {
const clone = newDate(date);
const cloneValue = utc ? clone.setUTCHours(0, 0, 0, 0) : clone.setHours(0, 0, 0, 0);
return new Date(cloneValue);
};
...@@ -76,7 +76,7 @@ export default { ...@@ -76,7 +76,7 @@ export default {
query: getShiftsForRotations, query: getShiftsForRotations,
variables() { variables() {
const startsAt = this.timeframeStartDate; const startsAt = this.timeframeStartDate;
const endsAt = new Date(nWeeksAfter(startsAt, 2)); const endsAt = nWeeksAfter(startsAt, 2);
return { return {
projectPath: this.projectPath, projectPath: this.projectPath,
...@@ -116,7 +116,7 @@ export default { ...@@ -116,7 +116,7 @@ export default {
case PRESET_TYPES.WEEKS: { case PRESET_TYPES.WEEKS: {
const firstDayOfTheLastWeek = this.timeframe[this.timeframe.length - 1]; const firstDayOfTheLastWeek = this.timeframe[this.timeframe.length - 1];
const firstDayOfTheNextTimeframe = nWeeksAfter(firstDayOfTheLastWeek, 1); const firstDayOfTheNextTimeframe = nWeeksAfter(firstDayOfTheLastWeek, 1);
const lastDayOfTimeframe = nDaysBefore(new Date(firstDayOfTheNextTimeframe), 1); const lastDayOfTimeframe = nDaysBefore(firstDayOfTheNextTimeframe, 1);
return `${formatDate(this.timeframe[0], 'mmmm d')} - ${formatDate( return `${formatDate(this.timeframe[0], 'mmmm d')} - ${formatDate(
lastDayOfTimeframe, lastDayOfTimeframe,
...@@ -142,10 +142,10 @@ export default { ...@@ -142,10 +142,10 @@ export default {
updateToViewPreviousTimeframe() { updateToViewPreviousTimeframe() {
switch (this.presetType) { switch (this.presetType) {
case PRESET_TYPES.DAYS: case PRESET_TYPES.DAYS:
this.timeframeStartDate = new Date(nDaysBefore(this.timeframeStartDate, 1)); this.timeframeStartDate = nDaysBefore(this.timeframeStartDate, 1);
break; break;
case PRESET_TYPES.WEEKS: case PRESET_TYPES.WEEKS:
this.timeframeStartDate = new Date(nWeeksBefore(this.timeframeStartDate, 2)); this.timeframeStartDate = nWeeksBefore(this.timeframeStartDate, 2);
break; break;
default: default:
break; break;
...@@ -154,10 +154,10 @@ export default { ...@@ -154,10 +154,10 @@ export default {
updateToViewNextTimeframe() { updateToViewNextTimeframe() {
switch (this.presetType) { switch (this.presetType) {
case PRESET_TYPES.DAYS: case PRESET_TYPES.DAYS:
this.timeframeStartDate = new Date(nDaysAfter(this.timeframeStartDate, 1)); this.timeframeStartDate = nDaysAfter(this.timeframeStartDate, 1);
break; break;
case PRESET_TYPES.WEEKS: case PRESET_TYPES.WEEKS:
this.timeframeStartDate = new Date(nWeeksAfter(this.timeframeStartDate, 2)); this.timeframeStartDate = nWeeksAfter(this.timeframeStartDate, 2);
break; break;
default: default:
break; break;
......
...@@ -35,7 +35,7 @@ export default { ...@@ -35,7 +35,7 @@ export default {
}, },
computed: { computed: {
currentTimeframeEndsAt() { currentTimeframeEndsAt() {
return new Date(nDaysAfter(this.timeframeItem, 1)); return nDaysAfter(this.timeframeItem, 1);
}, },
hoursUntilEndOfTimeFrame() { hoursUntilEndOfTimeFrame() {
return HOURS_IN_DAY - new Date(this.shiftRangeOverlap.overlapStartDate).getHours(); return HOURS_IN_DAY - new Date(this.shiftRangeOverlap.overlapStartDate).getHours();
......
...@@ -35,7 +35,7 @@ export default { ...@@ -35,7 +35,7 @@ export default {
}, },
computed: { computed: {
currentTimeframeEndsAt() { currentTimeframeEndsAt() {
return new Date(nDaysAfter(this.timeframeItem, DAYS_IN_DATE_WEEK)); return nDaysAfter(this.timeframeItem, DAYS_IN_DATE_WEEK);
}, },
daysUntilEndOfTimeFrame() { daysUntilEndOfTimeFrame() {
return ( return (
......
...@@ -6,9 +6,9 @@ import { LAST_WEEK, LAST_MONTH, LAST_90_DAYS } from './constants'; ...@@ -6,9 +6,9 @@ import { LAST_WEEK, LAST_MONTH, LAST_90_DAYS } from './constants';
// Compute all relative dates based on the _beginning_ of today // Compute all relative dates based on the _beginning_ of today
const startOfToday = new Date(new Date().setHours(0, 0, 0, 0)); const startOfToday = new Date(new Date().setHours(0, 0, 0, 0));
const lastWeek = new Date(nDaysBefore(startOfToday, 7)); const lastWeek = nDaysBefore(startOfToday, 7);
const lastMonth = new Date(nMonthsBefore(startOfToday, 1)); const lastMonth = nMonthsBefore(startOfToday, 1);
const last90Days = new Date(nDaysBefore(startOfToday, 90)); const last90Days = nDaysBefore(startOfToday, 90);
const apiDateFormatString = 'isoDateTime'; const apiDateFormatString = 'isoDateTime';
const titleDateFormatString = 'mmm d'; const titleDateFormatString = 'mmm d';
const sharedRequestParams = { const sharedRequestParams = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment