| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import includes from 'lodash/includes';
- import isDate from 'lodash/isDate';
- import { DateTime, dateTime, dateTimeForTimeZone, ISO_8601, isDateTime, DurationUnit } from './moment_wrapper';
- import { TimeZone } from '../types/index';
- const units: DurationUnit[] = ['y', 'M', 'w', 'd', 'h', 'm', 's'];
- export function isMathString(text: string | DateTime | Date): boolean {
- if (!text) {
- return false;
- }
- if (typeof text === 'string' && (text.substring(0, 3) === 'now' || text.includes('||'))) {
- return true;
- } else {
- return false;
- }
- }
- /**
- * Parses different types input to a moment instance. There is a specific formatting language that can be used
- * if text arg is string. See unit tests for examples.
- * @param text
- * @param roundUp See parseDateMath function.
- * @param timezone Only string 'utc' is acceptable here, for anything else, local timezone is used.
- */
- export function parse(text: string | DateTime | Date, roundUp?: boolean, timezone?: TimeZone): DateTime | undefined {
- if (!text) {
- return undefined;
- }
- if (typeof text !== 'string') {
- if (isDateTime(text)) {
- return text;
- }
- if (isDate(text)) {
- return dateTime(text);
- }
- // We got some non string which is not a moment nor Date. TS should be able to check for that but not always.
- return undefined;
- } else {
- let time;
- let mathString = '';
- let index;
- let parseString;
- if (text.substring(0, 3) === 'now') {
- time = dateTimeForTimeZone(timezone);
- mathString = text.substring('now'.length);
- } else {
- index = text.indexOf('||');
- if (index === -1) {
- parseString = text;
- mathString = ''; // nothing else
- } else {
- parseString = text.substring(0, index);
- mathString = text.substring(index + 2);
- }
- // We're going to just require ISO8601 timestamps, k?
- time = dateTime(parseString, ISO_8601);
- }
- if (!mathString.length) {
- return time;
- }
- return parseDateMath(mathString, time, roundUp);
- }
- }
- /**
- * Checks if text is a valid date which in this context means that it is either a Moment instance or it can be parsed
- * by parse function. See parse function to see what is considered acceptable.
- * @param text
- */
- export function isValid(text: string | DateTime): boolean {
- const date = parse(text);
- if (!date) {
- return false;
- }
- if (isDateTime(date)) {
- return date.isValid();
- }
- return false;
- }
- /**
- * Parses math part of the time string and shifts supplied time according to that math. See unit tests for examples.
- * @param mathString
- * @param time
- * @param roundUp If true it will round the time to endOf time unit, otherwise to startOf time unit.
- */
- // TODO: Had to revert Andrejs `time: moment.Moment` to `time: any`
- export function parseDateMath(mathString: string, time: any, roundUp?: boolean): DateTime | undefined {
- const strippedMathString = mathString.replace(/\s/g, '');
- const dateTime = time;
- let i = 0;
- const len = strippedMathString.length;
- while (i < len) {
- const c = strippedMathString.charAt(i++);
- let type;
- let num;
- let unit;
- if (c === '/') {
- type = 0;
- } else if (c === '+') {
- type = 1;
- } else if (c === '-') {
- type = 2;
- } else {
- return undefined;
- }
- if (isNaN(parseInt(strippedMathString.charAt(i), 10))) {
- num = 1;
- } else if (strippedMathString.length === 2) {
- num = strippedMathString.charAt(i);
- } else {
- const numFrom = i;
- while (!isNaN(parseInt(strippedMathString.charAt(i), 10))) {
- i++;
- if (i > 10) {
- return undefined;
- }
- }
- num = parseInt(strippedMathString.substring(numFrom, i), 10);
- }
- if (type === 0) {
- // rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M)
- if (num !== 1) {
- return undefined;
- }
- }
- unit = strippedMathString.charAt(i++);
- if (!includes(units, unit)) {
- return undefined;
- } else {
- if (type === 0) {
- if (roundUp) {
- dateTime.endOf(unit);
- } else {
- dateTime.startOf(unit);
- }
- } else if (type === 1) {
- dateTime.add(num, unit);
- } else if (type === 2) {
- dateTime.subtract(num, unit);
- }
- }
- }
- return dateTime;
- }
|