Source

utils/dates.js

/**
 * @namespace Utils
 * @category Utils
 * @module Dates*/

//@todo Remove: Use global i18n if available instead
import i18n from '@/i18n'

import moment from 'moment'
//import moment from 'moment-timezone'
//moment.tz.setDefault('Europe/Paris')
window._m = moment

export const frenchDatePattern = 'DD/MM/YYYY'
export const internationalDatePattern = 'DD-MM-YYYY'
export const englishDatePattern = 'MM/DD/YYYY'
export const englishTimePattern = 'hh:mm A'

/**
 * Use instead: formatDatetimeWithSeconds, formatDatetime, formatDate, formatTime and formatTimeWithSeconds
 *
 * @internal
 * @TODO Add milliseconds support
 * @param {String|Moment|Date} date Any valid date as string or Moment instance
 * @param {Boolean} options.onlyTime Default to false
 * @param {Boolean} options.onlyDate Default to false
 * @param {String} options.fallbackValue Value to display if invalid date (Default to an empty string)
 * @param {String} options.locale Locale code (i.g fr) (Defaults to i18n library current locale)
 * @param {String} options.inputFormat Custom input format (i.g HH:mm:ss MM-YYYY-DD)
 * @param {Boolean} options.seconds Add seconds to time format
 * @returns
 */
function formatDateInternal(date = null, options = {}) {
  if (typeof options !== 'object') {
    console.trace('WARN: formatDateInternal options expected to be an object')
  }

  let isMomentObject = (date || '')._isAMomentObject === true
  let lang = options.locale || i18n.locale || 'fr'
  let pattern = ''

  let timeSeparator = options.timeSeparator || ':'

  if (lang === 'fr' && options.useFrenchTimeSeparator) {
    timeSeparator = 'h'
  }

  /*
  if (options.useFrenchTimeSeparator !== undefined) {
    console.log('formatDateInternal', {
      lang,
      timeSeparator,
      options,
    })
  }*/

  switch (lang) {
    case 'en':
      pattern = `${englishDatePattern} ${englishTimePattern}`
      pattern = options.onlyDate ? `${englishDatePattern}` : pattern
      pattern = options.onlyTime ? englishTimePattern : pattern
      break
    case 'nl':
      pattern = `${internationalDatePattern} HH[${timeSeparator}]mm`
      pattern = options.onlyDate ? internationalDatePattern : pattern
      pattern = options.onlyTime ? `HH[${timeSeparator}]mm` : pattern
      break
    case 'fr':
    case 'es':
    default:
      pattern = `${frenchDatePattern} HH[${timeSeparator}]mm`
      pattern = options.onlyDate ? frenchDatePattern : pattern
      pattern = options.onlyTime ? `HH[${timeSeparator}]mm` : pattern
      if (options.seconds || options.milliseconds) {
        pattern = pattern
          .split(`HH[${timeSeparator}]mm`)
          .join(`HH[${timeSeparator}]mm[${timeSeparator}]ss`)
      }
      break
  }

  if (options.returnPattern) {
    return pattern
  }

  let isValid = isMomentObject
    ? date.isValid()
    : moment(date, options.inputFormat).isValid()
  if (isValid) {
    return isMomentObject
      ? date.format(pattern)
      : moment(date, options.inputFormat).format(pattern)
  } else {
    return options.fallbackValue || ''
  }
}

/**
 * Used by calendars?
 * @returns
 */
export function getDatePattern(options) {
  return formatDate(null, {
    ...options,
    returnPattern: true,
  })
}

/**
 * Used by datatable sorting plugin ($.fn.dataTable.moment(pattern))
 * @returns
 */
export function getDatetimePattern(options = {}) {
  return formatDateInternal(null, {
    ...options,
    returnPattern: true,
    seconds: options?.seconds === undefined ? true : options.seconds,
  })
}

/**
 * FR Example: DD/MM/YYYY HH:mm:ss
 * @param {*} date
 * @param {*} options
 * @returns
 */
export function formatDatetimeWithSeconds(date, options) {
  return formatDateInternal(date, {
    ...options,
    seconds: true,
  })
}
/**
 * FR Example: DD/MM/YYYY HH:mm
 * @param {*} date
 * @param {*} options
 * @returns
 */
export function formatDatetime(date, options) {
  return formatDateInternal(date, options)
}
/**
 * FR Example: DD/MM/YYYY
 * @param {*} date
 * @param {*} options
 * @returns
 */
export function formatDate(date, options) {
  return formatDateInternal(date, {
    ...options,
    onlyDate: true,
  })
}
/**
 * FR example: HH:mm
 * @param {*} date
 * @param {*} options
 * @returns
 */
export function formatTime(date, options) {
  return formatDateInternal(date, {
    ...options,
    onlyTime: true,
  })
}
/**
 * FR example: HH:mm:ss
 * @param {*} date
 * @param {*} options
 * @returns
 */
export function formatTimeWithSeconds(date, options) {
  return formatDateInternal(date, {
    ...options,
    onlyTime: true,
    seconds: true,
  })
}

/**
 * @description Format seconds to 00:00:00
 * @example
 * formatSeconds(70)
 * 00:01:10
 */
export function formatSeconds(seconds) {
  let d = moment.duration(seconds * 1000)
  return (
    Math.floor(d.asHours()) + moment.utc(seconds * 1000).format('[:]mm[:]ss')
  )
}

export function secondsToDuration(seconds, format = '[:]mm:ss') {
  return (
    Math.floor(moment.duration(seconds * 1000).asHours()) +
    moment.utc(seconds * 1000).format(format)
  )
}

/**
 * Valid date parseable with moment
 * @param {*} date
 */
export function datetimeToTimestamp(datetime, inputFormat) {
  return moment(datetime, inputFormat)._d.getTime()
}

export const isMomentToday = (momentValue) =>
  moment(momentValue).isSame(new Date(), 'day')

export function areDatesConsecutive(dates) {
  for (let i = 0; i < dates.length - 1; i++) {
    const currentDate = moment(dates[i])
    const nextDate = moment(dates[i + 1])

    if (!nextDate.isSame(currentDate.add(1, 'days'), 'day')) {
      return false
    }
  }

  return true
}