1
0
mirror of https://gitlab.com/bramw/baserow.git synced 2024-11-21 23:37:55 +00:00
bramw_baserow/web-frontend/modules/database/utils/date.js

202 lines
6.1 KiB
JavaScript

import moment from '@baserow/modules/core/moment'
const dateMapping = {
EU: {
momentFormat: 'DD/MM/YYYY',
humanFormat: 'dd/mm/yyyy',
},
US: {
momentFormat: 'MM/DD/YYYY',
humanFormat: 'mm/dd/yyyy',
},
ISO: {
momentFormat: 'YYYY-MM-DD',
humanFormat: 'yyyy-mm-dd',
},
}
const timeMapping = {
12: {
momentFormat: 'hh:mm A',
humanFormat: 'hh:mm AM',
},
24: {
momentFormat: 'HH:mm',
humanFormat: 'hh:mm',
},
}
export const getDateMomentFormat = (type) => {
if (!Object.prototype.hasOwnProperty.call(dateMapping, type)) {
throw new Error(`${type} wasn't found in the date mapping.`)
}
return dateMapping[type].momentFormat
}
export const getTimeMomentFormat = (type) => {
if (!Object.prototype.hasOwnProperty.call(timeMapping, type)) {
throw new Error(`${type} wasn't found in the time mapping.`)
}
return timeMapping[type].momentFormat
}
export const getDateHumanReadableFormat = (type) => {
if (!Object.prototype.hasOwnProperty.call(dateMapping, type)) {
throw new Error(`${type} wasn't found in the date mapping.`)
}
return dateMapping[type].humanFormat
}
export const getTimeHumanReadableFormat = (type) => {
if (!Object.prototype.hasOwnProperty.call(timeMapping, type)) {
throw new Error(`${type} wasn't found in the time mapping.`)
}
return timeMapping[type].humanFormat
}
/**
* Returns the timezone for a given field. If the field doesn't have a timezone
* set, the timezone of the user is returned.
*
* @param {Object} field The field object
* @param {boolean} guess Whether or not to try guess the users timezone
* @returns {String} The timezone for the field
* @example
* getFieldTimezone({ date_include_time: true, date_force_timezone: 'Europe/Amsterdam' }) // => 'Europe/Amsterdam'
* getFieldTimezone({ date_include_time: false }) // => 'UTC'
*/
export const getFieldTimezone = (field, guess = true) => {
return field.date_include_time
? field.date_force_timezone ||
(guess && !process.server && moment.tz.guess())
: null
}
/**
* Returns the timezone abbreviation for a given field and value.
* If the value is null or undefined and force=false, an empty string is returned.
*
* @param {Object} field The field object
* @param {String | moment} value The value to parse into a moment object
* @param {Object} options
* @param {String} options.format The format to parse the value with
* @param {Boolean} options.replace Whether to replace the timezone or not
*/
export const getCellTimezoneAbbr = (
field,
value,
{ format = 'z', force = false } = {}
) => {
if (!force && (value === null || value === undefined)) {
return ''
}
const timezone = getFieldTimezone(field)
return timezone
? moment
.utc(value || undefined)
.tz(timezone)
.format(format)
: 'UTC'
}
export const DATE_FILTER_VALUE_SEPARATOR = '?'
/**
* Splits the timezone and the filter value from a filter value.
*
* @param {*} value The filter value
* @param {*} separator The separator between the timezone and the filter value
* @returns {Array} An array with the timezone and the filter value
*/
export const splitTimezoneAndFilterValue = (
value,
separator = DATE_FILTER_VALUE_SEPARATOR
) => {
let timezone = null
let filterValue
if (value.includes(separator)) {
// if the filter value already contains a timezone, use it
;[timezone, filterValue] = value.split(separator)
} else {
// fallback for values before timezone was added to the filter value
filterValue = value
}
timezone = moment.tz.zone(timezone) ? timezone : null
return [timezone, filterValue]
}
/**
* Split the filter value for multi-step date filters.
* @param {String} value The filter value
* @param {String} separator The separator between the timezone, the filter value and the operator
* @returns {Array} An array with the timezone, the filter value and the operator
*/
export const splitMultiStepDateValue = (
value,
separator = DATE_FILTER_VALUE_SEPARATOR
) => {
const splittedValue = value.split(separator)
if (splittedValue.length === 3) {
return splittedValue
} else if (splittedValue.length === 2) {
// let's assume the timezone has not been provided
return [null, splittedValue[0], splittedValue[1]]
} else {
return [null, '', '']
}
}
/**
* Compares an item with a previous item to determine
* whether a day separator should be rendered.
*
* @param {*} items All items that contains the timestamp property
* @param {String} prop The name of the property that holds the timestamp
* @param {Number} index Index at which we need to decide if previous and
* next item's datetimes differ
* @returns {Boolean} Whether the timestamps around the index warrant
* rendering a date separator
*/
export const shouldDisplayDateSeparator = (items, prop, index) => {
if (index === items.length - 1) {
return true
}
const tzone = moment.tz.guess()
const prevDate = moment.utc(items[index][prop]).tz(tzone)
const currentDate = moment.utc(items[index + 1][prop]).tz(tzone)
return !prevDate.isSame(currentDate, 'day')
}
/**
* Formats output for date separators when separating items based on
* day (today, yesterday, etc.)
*
* @param {moment} timestamp The datetime to format
* @returns {String} The formatted timestamp
*/
export const formatDateSeparator = (timestamp) => {
return moment.utc(timestamp).tz(moment.tz.guess()).calendar(null, {
sameDay: '[Today]',
lastDay: '[Yesterday]',
lastWeek: 'LL',
sameElse: 'LL',
})
}
/**
* Prepares a value for a multi-step date filter. It combines the timezone,
* the filter value and the operator into a single string. It puts the operator
* at the end to keep the compatibility with the old filter values.
*
* @param {String} filterValue The filter value
* @param {String} timezone The timezone
* @param {String} operator The date filter operator to use
* @returns {String} The combined value to send to the backend
*/
export const prepareMultiStepDateValue = (filterValue, timezone, operator) => {
const sep = DATE_FILTER_VALUE_SEPARATOR
return `${timezone}${sep}${filterValue}${sep}${operator}`
}