Skip to content

Instantly share code, notes, and snippets.

@vandy
Last active February 4, 2020 20:27
Show Gist options
  • Save vandy/2e10c67e778e17e6b5832fbed39bb948 to your computer and use it in GitHub Desktop.
Save vandy/2e10c67e778e17e6b5832fbed39bb948 to your computer and use it in GitHub Desktop.

Revisions

  1. vandy revised this gist Feb 4, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions date-utils.js
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    /**
    * Compares a date with today in the client time zone. The comparison is day-wise,
    * Compares a date with today in the client's time zone. The comparison is day-wise,
    * so that all dates since today's midnight till the next midnight are considered "today".
    * Yesterday and tomorrow are separate from the past and future.
    *
    @@ -16,7 +16,7 @@ export function relativeToLocaleToday(dateRepresentation) {
    }

    /**
    * Compares a date with the reference date in the client time zone. The comparison is day-wise,
    * Compares a date with the reference date in the client's time zone. The comparison is day-wise,
    * so that all dates since the date's midnight till the next midnight are considered "same day".
    *
    * @param dateRepresentation {string|number|Date}
  2. vandy created this gist Sep 20, 2019.
    113 changes: 113 additions & 0 deletions date-utils.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,113 @@
    /**
    * Compares a date with today in the client time zone. The comparison is day-wise,
    * so that all dates since today's midnight till the next midnight are considered "today".
    * Yesterday and tomorrow are separate from the past and future.
    *
    * @param dateRepresentation {string|number|Date}
    * @returns {number}
    * +2 - date is in the future (after tomorrow)
    * +1 - tomorrow
    * 0 - today
    * -1 - yesterday
    * -2 - date is in the past (before yesterday)
    */
    export function relativeToLocaleToday(dateRepresentation) {
    return relativeToDate(dateRepresentation, Date.now());
    }

    /**
    * Compares a date with the reference date in the client time zone. The comparison is day-wise,
    * so that all dates since the date's midnight till the next midnight are considered "same day".
    *
    * @param dateRepresentation {string|number|Date}
    * @param to {string|number|Date}
    * @returns {number}
    * +2 - the date is after the reference date (2 days or more)
    * +1 - the date is next to the reference date
    * 0 - the same day
    * -1 - the date is one day before the reference date
    * -2 - the date is earlier the reference date (2 days or more)
    */
    export function relativeToDate(dateRepresentation, to) {
    const date = new Date(dateRepresentation);
    const referenceDate = new Date(to);
    if (referenceDate.toDateString() === date.toDateString()) {
    return 0;
    }

    const inFuture = date > referenceDate;
    const midnight = new Date(
    referenceDate.getFullYear(),
    referenceDate.getMonth(),
    referenceDate.getDate() + (inFuture ? 2 : -1)
    );
    if (inFuture) {
    return midnight > date
    ? 1
    : 2;
    }

    return midnight <= date
    ? -1
    : -2;
    }

    /**
    * Returns a range of dates between 'from' and 'to' exclusively: 'from', [N+1, N+2, ...], 'to'.
    * If 'from' is greater than 'to', the range is reversed: 'from', [N-1, N-2, ...], 'to'.
    * If 'include' argument is true and 'from' is the same day as 'to' (time may be different),
    * the range would contain only one element, which is max('from', 'to').
    *
    * @param from {string|number|Date}
    * @param to {string|number|Date}
    * @param [include=false] {boolean} -
    * include 'from' and/or 'to' to the resulting array.
    * @param [transform=null] {null|true|Function} -
    * if null, time of the dates between 'from' and 'to' would be the same as 'from'.
    * if true, time of the dates would be set to locale midnight,
    * if Function, each Date in the range would be passed to the function,
    * returned value is used in the resulting array.
    * @returns {[]}
    */
    export function datesRange(from, to, {include = false, transform = null} = {}) {
    const range = [];
    from = new Date(from);
    to = new Date(to);
    const reversed = from > to;
    if (reversed) {
    [from, to] = [to, from];
    }
    const insert = reversed ? range.unshift.bind(range) : range.push.bind(range);
    const formatter = typeof transform === 'function' ? transform : function (d) {
    if (transform === true) {
    d.setHours(0);
    d.setMinutes(0);
    d.setSeconds(0);
    d.setMilliseconds(0);
    }

    return d;
    };
    const fromToOffset = relativeToDate(from, to);
    if (fromToOffset < -1) {
    const toMidnight = new Date(to.getFullYear(), to.getMonth(), to.getDate());
    const nextDay = new Date(from);
    while (nextDay.setDate(nextDay.getDate() + 1) < toMidnight) {
    insert(formatter(new Date(nextDay)));
    }
    }

    if (include) {
    insert(formatter(to));
    if (fromToOffset) {
    const resultFrom = formatter(from);
    if (reversed) {
    range.push(resultFrom);
    } else {
    range.unshift(resultFrom);
    }
    }
    }

    return range;
    }