Skip to content

Commit

Permalink
move relativeTimeToDate to Utils
Browse files Browse the repository at this point in the history
  • Loading branch information
cbaker6 committed Jan 1, 2022
1 parent 44c2c8d commit 6481a5a
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 142 deletions.
23 changes: 12 additions & 11 deletions spec/MongoTransform.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
const transform = require('../lib/Adapters/Storage/Mongo/MongoTransform');
const dd = require('deep-diff');
const mongodb = require('mongodb');
const Utils = require('../lib/Utils');

describe('parseObjectToMongoObjectForCreate', () => {
it('a basic number', done => {
Expand Down Expand Up @@ -592,7 +593,7 @@ describe('relativeTimeToDate', () => {
describe('In the future', () => {
it('should parse valid natural time', () => {
const text = 'in 1 year 2 weeks 12 days 10 hours 24 minutes 30 seconds';
const { result, status, info } = transform.relativeTimeToDate(text, now);
const { result, status, info } = Utils.relativeTimeToDate(text, now);
expect(result.toISOString()).toBe('2018-10-22T23:52:46.617Z');
expect(status).toBe('success');
expect(info).toBe('future');
Expand All @@ -602,7 +603,7 @@ describe('relativeTimeToDate', () => {
describe('In the past', () => {
it('should parse valid natural time', () => {
const text = '2 days 12 hours 1 minute 12 seconds ago';
const { result, status, info } = transform.relativeTimeToDate(text, now);
const { result, status, info } = Utils.relativeTimeToDate(text, now);
expect(result.toISOString()).toBe('2017-09-24T01:27:04.617Z');
expect(status).toBe('success');
expect(info).toBe('past');
Expand All @@ -612,7 +613,7 @@ describe('relativeTimeToDate', () => {
describe('From now', () => {
it('should equal current time', () => {
const text = 'now';
const { result, status, info } = transform.relativeTimeToDate(text, now);
const { result, status, info } = Utils.relativeTimeToDate(text, now);
expect(result.toISOString()).toBe('2017-09-26T13:28:16.617Z');
expect(status).toBe('success');
expect(info).toBe('present');
Expand All @@ -621,54 +622,54 @@ describe('relativeTimeToDate', () => {

describe('Error cases', () => {
it('should error if string is completely gibberish', () => {
expect(transform.relativeTimeToDate('gibberishasdnklasdnjklasndkl123j123')).toEqual({
expect(Utils.relativeTimeToDate('gibberishasdnklasdnjklasndkl123j123')).toEqual({
status: 'error',
info: "Time should either start with 'in' or end with 'ago'",
});
});

it('should error if string contains neither `ago` nor `in`', () => {
expect(transform.relativeTimeToDate('12 hours 1 minute')).toEqual({
expect(Utils.relativeTimeToDate('12 hours 1 minute')).toEqual({
status: 'error',
info: "Time should either start with 'in' or end with 'ago'",
});
});

it('should error if there are missing units or numbers', () => {
expect(transform.relativeTimeToDate('in 12 hours 1')).toEqual({
expect(Utils.relativeTimeToDate('in 12 hours 1')).toEqual({
status: 'error',
info: 'Invalid time string. Dangling unit or number.',
});

expect(transform.relativeTimeToDate('12 hours minute ago')).toEqual({
expect(Utils.relativeTimeToDate('12 hours minute ago')).toEqual({
status: 'error',
info: 'Invalid time string. Dangling unit or number.',
});
});

it('should error on floating point numbers', () => {
expect(transform.relativeTimeToDate('in 12.3 hours')).toEqual({
expect(Utils.relativeTimeToDate('in 12.3 hours')).toEqual({
status: 'error',
info: "'12.3' is not an integer.",
});
});

it('should error if numbers are invalid', () => {
expect(transform.relativeTimeToDate('12 hours 123a minute ago')).toEqual({
expect(Utils.relativeTimeToDate('12 hours 123a minute ago')).toEqual({
status: 'error',
info: "'123a' is not an integer.",
});
});

it('should error on invalid interval units', () => {
expect(transform.relativeTimeToDate('4 score 7 years ago')).toEqual({
expect(Utils.relativeTimeToDate('4 score 7 years ago')).toEqual({
status: 'error',
info: "Invalid interval: 'score'",
});
});

it("should error when string contains 'ago' and 'in'", () => {
expect(transform.relativeTimeToDate('in 1 day 2 minutes ago')).toEqual({
expect(Utils.relativeTimeToDate('in 1 day 2 minutes ago')).toEqual({
status: 'error',
info: "Time cannot have both 'in' and 'ago'",
});
Expand Down
131 changes: 2 additions & 129 deletions src/Adapters/Storage/Mongo/MongoTransform.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import log from '../../../logger';
import _ from 'lodash';
var mongodb = require('mongodb');
var Parse = require('parse/node').Parse;
const Utils = require('../../../Utils');

const transformKey = (className, fieldName, schema) => {
// Check if the schema is known since it's a built-in field.
Expand Down Expand Up @@ -634,133 +635,6 @@ function transformTopLevelAtom(atom, field) {
}
}

function relativeTimeToDate(text, now = new Date()) {
text = text.toLowerCase();

let parts = text.split(' ');

// Filter out whitespace
parts = parts.filter(part => part !== '');

const future = parts[0] === 'in';
const past = parts[parts.length - 1] === 'ago';

if (!future && !past && text !== 'now') {
return {
status: 'error',
info: "Time should either start with 'in' or end with 'ago'",
};
}

if (future && past) {
return {
status: 'error',
info: "Time cannot have both 'in' and 'ago'",
};
}

// strip the 'ago' or 'in'
if (future) {
parts = parts.slice(1);
} else {
// past
parts = parts.slice(0, parts.length - 1);
}

if (parts.length % 2 !== 0 && text !== 'now') {
return {
status: 'error',
info: 'Invalid time string. Dangling unit or number.',
};
}

const pairs = [];
while (parts.length) {
pairs.push([parts.shift(), parts.shift()]);
}

let seconds = 0;
for (const [num, interval] of pairs) {
const val = Number(num);
if (!Number.isInteger(val)) {
return {
status: 'error',
info: `'${num}' is not an integer.`,
};
}

switch (interval) {
case 'yr':
case 'yrs':
case 'year':
case 'years':
seconds += val * 31536000; // 365 * 24 * 60 * 60
break;

case 'wk':
case 'wks':
case 'week':
case 'weeks':
seconds += val * 604800; // 7 * 24 * 60 * 60
break;

case 'd':
case 'day':
case 'days':
seconds += val * 86400; // 24 * 60 * 60
break;

case 'hr':
case 'hrs':
case 'hour':
case 'hours':
seconds += val * 3600; // 60 * 60
break;

case 'min':
case 'mins':
case 'minute':
case 'minutes':
seconds += val * 60;
break;

case 'sec':
case 'secs':
case 'second':
case 'seconds':
seconds += val;
break;

default:
return {
status: 'error',
info: `Invalid interval: '${interval}'`,
};
}
}

const milliseconds = seconds * 1000;
if (future) {
return {
status: 'success',
info: 'future',
result: new Date(now.valueOf() + milliseconds),
};
} else if (past) {
return {
status: 'success',
info: 'past',
result: new Date(now.valueOf() - milliseconds),
};
} else {
return {
status: 'success',
info: 'present',
result: new Date(now.valueOf()),
};
}
}

// Transforms a query constraint from REST API format to Mongo format.
// A constraint is something with fields like $lt.
// If it is not a valid constraint but it could be a valid something
Expand Down Expand Up @@ -813,7 +687,7 @@ function transformConstraint(constraint, field, count = false) {
);
}

const parserResult = relativeTimeToDate(val.$relativeTime);
const parserResult = Utils.relativeTimeToDate(val.$relativeTime);
if (parserResult.status === 'success') {
answer[key] = parserResult.result;
break;
Expand Down Expand Up @@ -1556,7 +1430,6 @@ module.exports = {
transformUpdate,
transformWhere,
mongoObjectToParseObject,
relativeTimeToDate,
transformConstraint,
transformPointerString,
};
4 changes: 2 additions & 2 deletions src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { v4 as uuidv4 } from 'uuid';
import sql from './sql';
import { StorageAdapter } from '../StorageAdapter';
import type { SchemaType, QueryType, QueryOptions } from '../StorageAdapter';
import { relativeTimeToDate } from '../Mongo/MongoTransform';
const Utils = require('../../../Utils');

const PostgresRelationDoesNotExistError = '42P01';
const PostgresDuplicateRelationError = '42P07';
Expand Down Expand Up @@ -797,7 +797,7 @@ const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClaus
'$relativeTime can only be used with Date field'
);
}
const parserResult = relativeTimeToDate(postgresValue.$relativeTime);
const parserResult = Utils.relativeTimeToDate(postgresValue.$relativeTime);
if (parserResult.status === 'success') {
postgresValue = toPostgresValue(parserResult.result);
} else {
Expand Down
Loading

0 comments on commit 6481a5a

Please sign in to comment.