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) => {
};
/**
* 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 {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) =>
new Date(newDate(date)).setDate(date.getDate() + numberOfDays);
export const nDaysAfter = (date, numberOfDays, { utc = false } = {}) => {
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 {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 {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) =>
new Date(newDate(date)).setDate(date.getDate() + DAYS_IN_WEEK * numberOfWeeks);
export const nWeeksAfter = (date, numberOfWeeks, options) =>
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 {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 {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) =>
new Date(newDate(date)).setMonth(date.getMonth() + numberOfMonths);
export const nMonthsAfter = (date, numberOfMonths, { utc = false } = {}) => {
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 {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
*
* @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
*/
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
......@@ -933,3 +991,22 @@ export const isToday = (date) => {
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 {
query: getShiftsForRotations,
variables() {
const startsAt = this.timeframeStartDate;
const endsAt = new Date(nWeeksAfter(startsAt, 2));
const endsAt = nWeeksAfter(startsAt, 2);
return {
projectPath: this.projectPath,
......@@ -116,7 +116,7 @@ export default {
case PRESET_TYPES.WEEKS: {
const firstDayOfTheLastWeek = this.timeframe[this.timeframe.length - 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(
lastDayOfTimeframe,
......@@ -142,10 +142,10 @@ export default {
updateToViewPreviousTimeframe() {
switch (this.presetType) {
case PRESET_TYPES.DAYS:
this.timeframeStartDate = new Date(nDaysBefore(this.timeframeStartDate, 1));
this.timeframeStartDate = nDaysBefore(this.timeframeStartDate, 1);
break;
case PRESET_TYPES.WEEKS:
this.timeframeStartDate = new Date(nWeeksBefore(this.timeframeStartDate, 2));
this.timeframeStartDate = nWeeksBefore(this.timeframeStartDate, 2);
break;
default:
break;
......@@ -154,10 +154,10 @@ export default {
updateToViewNextTimeframe() {
switch (this.presetType) {
case PRESET_TYPES.DAYS:
this.timeframeStartDate = new Date(nDaysAfter(this.timeframeStartDate, 1));
this.timeframeStartDate = nDaysAfter(this.timeframeStartDate, 1);
break;
case PRESET_TYPES.WEEKS:
this.timeframeStartDate = new Date(nWeeksAfter(this.timeframeStartDate, 2));
this.timeframeStartDate = nWeeksAfter(this.timeframeStartDate, 2);
break;
default:
break;
......
......@@ -35,7 +35,7 @@ export default {
},
computed: {
currentTimeframeEndsAt() {
return new Date(nDaysAfter(this.timeframeItem, 1));
return nDaysAfter(this.timeframeItem, 1);
},
hoursUntilEndOfTimeFrame() {
return HOURS_IN_DAY - new Date(this.shiftRangeOverlap.overlapStartDate).getHours();
......
......@@ -35,7 +35,7 @@ export default {
},
computed: {
currentTimeframeEndsAt() {
return new Date(nDaysAfter(this.timeframeItem, DAYS_IN_DATE_WEEK));
return nDaysAfter(this.timeframeItem, DAYS_IN_DATE_WEEK);
},
daysUntilEndOfTimeFrame() {
return (
......
......@@ -6,9 +6,9 @@ import { LAST_WEEK, LAST_MONTH, LAST_90_DAYS } from './constants';
// Compute all relative dates based on the _beginning_ of today
const startOfToday = new Date(new Date().setHours(0, 0, 0, 0));
const lastWeek = new Date(nDaysBefore(startOfToday, 7));
const lastMonth = new Date(nMonthsBefore(startOfToday, 1));
const last90Days = new Date(nDaysBefore(startOfToday, 90));
const lastWeek = nDaysBefore(startOfToday, 7);
const lastMonth = nMonthsBefore(startOfToday, 1);
const last90Days = nDaysBefore(startOfToday, 90);
const apiDateFormatString = 'isoDateTime';
const titleDateFormatString = 'mmm d';
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