Skip to content

Commit

Permalink
tests for all time functions
Browse files Browse the repository at this point in the history
  • Loading branch information
KSDaemon committed Feb 28, 2025
1 parent 4aa2b41 commit 0037104
Showing 1 changed file with 275 additions and 12 deletions.
287 changes: 275 additions & 12 deletions packages/cubejs-backend-shared/test/time.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import moment from 'moment-timezone';
import { localTimestampToUtc, timeSeries, isPredefinedGranularity, timeSeriesFromCustomInterval } from '../src';
import {
localTimestampToUtc,
timeSeries,
isPredefinedGranularity,
timeSeriesFromCustomInterval,
extractDate,
utcToLocalTimeZone,
addSecondsToLocalTimestamp,
reformatInIsoLocal,
} from '../src';

describe('time', () => {
describe('timeSeries', () => {
it('time series - day', () => {
expect(timeSeries('day', ['2021-01-01', '2021-01-02'])).toEqual([
['2021-01-01T00:00:00.000', '2021-01-01T23:59:59.999'],
Expand Down Expand Up @@ -177,19 +186,273 @@ describe('time', () => {
timeSeriesFromCustomInterval('10 minutes 15 seconds', ['1970-01-01', '2021-01-02'], moment('2021-02-01 09:59:45'));
}).toThrowError(/The count of generated date ranges.*for the request.*is over limit/);
});
});

it('inDbTimeZone', () => {
expect(localTimestampToUtc('UTC', 'YYYY-MM-DD[T]HH:mm:ss.SSSSSS[Z]', '2020-01-01T00:00:00.000000')).toEqual(
'2020-01-01T00:00:00.000000Z'
);

expect(localTimestampToUtc('UTC', 'YYYY-MM-DD[T]HH:mm:ss.SSSSSS[Z]', '2020-01-31T23:59:59.999999')).toEqual(
'2020-01-31T23:59:59.999999Z'
);
});

describe('predefinedGranularity', () => {
it('isPredefinedGranularity', () => {
expect(isPredefinedGranularity('day')).toBeTruthy();
expect(isPredefinedGranularity('fiscal_year_by_1st_feb')).toBeFalsy();
});
});

describe('extractDate', () => {
it('should return null if data is empty', () => {
expect(extractDate(null)).toBeNull();
expect(extractDate(undefined)).toBeNull();
expect(extractDate([])).toBeNull();
expect(extractDate('')).toBeNull();
});

it('should return null if no valid date is found in data', () => {
expect(extractDate([{}])).toBeNull();
expect(extractDate([{ someKey: 'invalid date' }])).toBeNull();
});

it('should parse a date with UTC timezone', () => {
const input = [{ date: '2025-02-28T12:00:00Z' }];
const result = extractDate(input);
expect(result).toBe('2025-02-28T12:00:00.000');
});

it('should parse a date with an offset timezone', () => {
const input = [{ date: '2025-02-28T12:00:00+03:00' }];
const result = extractDate(input);
expect(result).toBe('2025-02-28T09:00:00.000');
});

it('should parse a date without timezone as UTC', () => {
const input = [{ date: '2025-02-28 12:00:00' }];
const result = extractDate(input);
expect(result).toBe('2025-02-28T12:00:00.000');
});

it('should handle multiple formats', () => {
const input1 = [{ date: '2025-02-28 12:00:00' }];
const input2 = [{ date: '2025-02-28T12:00:00.000' }];
const input3 = [{ date: '2025-02-28T12:00:00Z' }];
const input4 = [{ date: '2025-02-28T12:00:00+03:00' }];

expect(extractDate(input1)).toBe('2025-02-28T12:00:00.000');
expect(extractDate(input2)).toBe('2025-02-28T12:00:00.000');
expect(extractDate(input3)).toBe('2025-02-28T12:00:00.000');
expect(extractDate(input4)).toBe('2025-02-28T09:00:00.000');
});
});

describe('localTimestampToUtc', () => {
it('should return null if timestamp is empty', () => {
expect(localTimestampToUtc('UTC', 'YYYY-MM-DDTHH:mm:ss.SSS', '')).toBeNull();
expect(localTimestampToUtc('UTC', 'YYYY-MM-DDTHH:mm:ss.SSS')).toBeNull();
});

it('should throw an error for unknown timezone', () => {
expect(() => localTimestampToUtc('Invalid/Timezone', 'YYYY-MM-DDTHH:mm:ss.SSS', '2025-02-28T12:00:00.000'))
.toThrowError('Unknown timezone: Invalid/Timezone');
});

it('should convert timestamp with timezone to UTC for format YYYY-MM-DD[T]HH:mm:ss.SSS[Z]', () => {
const timestamp = '2025-02-28T11:00:00.000';
const timezone = 'Europe/Kiev';
const result = localTimestampToUtc(timezone, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]', timestamp);
expect(result).toBe('2025-02-28T09:00:00.000Z');
});

it('should convert timestamp with timezone to UTC for format YYYY-MM-DDTHH:mm:ss.SSSZ', () => {
const timestamp = '2025-02-28T11:00:00.000';
const timezone = 'Europe/Kiev';
const result = localTimestampToUtc(timezone, 'YYYY-MM-DDTHH:mm:ss.SSSZ', timestamp);
expect(result).toBe('2025-02-28T09:00:00.000Z');
});

it('should convert timestamp with microseconds to UTC for format YYYY-MM-DD[T]HH:mm:ss.SSSSSS[Z]', () => {
const timezone = 'Europe/Kiev';
let timestamp = '2025-02-28T11:00:00.123456';
let result = localTimestampToUtc(timezone, 'YYYY-MM-DD[T]HH:mm:ss.SSSSSS[Z]', timestamp);
expect(result).toBe('2025-02-28T09:00:00.123000Z'); // microseconds are zeroed :(

timestamp = '2025-02-28T11:00:00.000000';
result = localTimestampToUtc(timezone, 'YYYY-MM-DD[T]HH:mm:ss.SSSSSS[Z]', timestamp);
expect(result).toBe('2025-02-28T09:00:00.000000Z'); // microseconds are zeroed :(

timestamp = '2025-02-28T11:00:00.999999';
result = localTimestampToUtc(timezone, 'YYYY-MM-DD[T]HH:mm:ss.SSSSSS[Z]', timestamp);
expect(result).toBe('2025-02-28T09:00:00.999999Z'); // microseconds are zeroed :(
});

it('should convert timestamp with timezone to UTC for format YYYY-MM-DDTHH:mm:ss.SSSSSS', () => {
const timezone = 'Europe/Kiev';
let timestamp = '2025-02-28T11:00:00.123456';
let result = localTimestampToUtc(timezone, 'YYYY-MM-DDTHH:mm:ss.SSSSSS', timestamp);
expect(result).toBe('2025-02-28T09:00:00.123000');

timestamp = '2025-02-28T11:00:00.000000';
result = localTimestampToUtc(timezone, 'YYYY-MM-DDTHH:mm:ss.SSSSSS', timestamp);
expect(result).toBe('2025-02-28T09:00:00.000000');

timestamp = '2025-02-28T11:00:00.999999';
result = localTimestampToUtc(timezone, 'YYYY-MM-DDTHH:mm:ss.SSSSSS', timestamp);
expect(result).toBe('2025-02-28T09:00:00.999999');
});

it('should convert timestamp without timezone to UTC for format YYYY-MM-DDTHH:mm:ss.SSS', () => {
const timestamp = '2025-02-28T12:00:00.000';
const timezone = 'UTC';
const result = localTimestampToUtc(timezone, 'YYYY-MM-DDTHH:mm:ss.SSS', timestamp);
expect(result).toBe('2025-02-28T12:00:00.000'); // UTC
});

it('should correctly handle timestamp without time zone', () => {
const timestamp = '2025-02-28T12:00:00.000';
const timezone = 'America/New_York';
const result = localTimestampToUtc(timezone, 'YYYY-MM-DDTHH:mm:ss.SSS', timestamp);
expect(result).toBe('2025-02-28T17:00:00.000'); // America/New_York is UTC-5 during daylight saving time
});
});

describe('utcToLocalTimeZone', () => {
it('should return null if no timestamp is provided', () => {
expect(utcToLocalTimeZone('Europe/Kiev', 'YYYY-MM-DDTHH:mm:ss.SSS', undefined)).toBeNull();
});

it('should throw an error for an unknown timezone', () => {
expect(() => utcToLocalTimeZone('Unknown/Zone', 'YYYY-MM-DDTHH:mm:ss.SSS', '2025-02-28T10:00:00.000'))
.toThrow('Unknown timezone: Unknown/Zone');
});

it('should convert UTC to specified timezone with timestamp format "YYYY-MM-DDTHH:mm:ss.SSS"', () => {
const timestamp = '2025-02-28T10:00:00.000';
const expected = '2025-02-28T12:00:00.000';

expect(utcToLocalTimeZone('Europe/Kiev', 'YYYY-MM-DDTHH:mm:ss.SSS', timestamp)).toBe(expected);
});

it('should convert UTC to specified timezone with timestamp format "YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"', () => {
const timestamp = '2025-02-28T10:00:00.000';
const expected = '2025-02-28T12:00:00.000Z';

expect(utcToLocalTimeZone('Europe/Kiev', 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]', timestamp)).toBe(expected);
});

it('should handle timestamps with microseconds correctly', () => {
const timestamp = '2025-02-28T10:00:00.123456Z';
const expected = '2025-02-28T12:00:00.123000'; // microseconds are zeroed

expect(utcToLocalTimeZone('Europe/Kiev', 'YYYY-MM-DDTHH:mm:ss.SSSSSS', timestamp)).toBe(expected);
});

it('should handle UTC timestamp and correctly shift to target timezone', () => {
const timestamp = '2025-02-28T12:00:00.000Z';
const expected = '2025-02-28T14:00:00.000';

expect(utcToLocalTimeZone('Europe/Kiev', 'YYYY-MM-DDTHH:mm:ss.SSS', timestamp)).toBe(expected);
});

it('should correctly handle UTC to timezone conversion with timestamp format without milliseconds', () => {
const timestamp = '2025-02-28T10:00:00Z';
const expected = '2025-02-28T12:00:00';

expect(utcToLocalTimeZone('Europe/Kiev', 'YYYY-MM-DDTHH:mm:ss', timestamp)).toBe(expected);
});

it('should return the local time as UTC format if no milliseconds are present', () => {
const timestamp = '2025-02-28T10:00:00Z';
const expected = '2025-02-28T12:00:00.000Z';

expect(utcToLocalTimeZone('Europe/Kiev', 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]', timestamp)).toBe(expected);
});
});

describe('addSecondsToLocalTimestamp', () => {
it('should throw an error for an unknown timezone', () => {
const timestamp = '2025-02-28T12:00:00.000';
const unknownTimezone = 'Unknown/Zone';
const seconds = 10;

expect(() => addSecondsToLocalTimestamp(timestamp, unknownTimezone, seconds))
.toThrow('Unknown timezone: Unknown/Zone');
});

it('should correctly add seconds to a timestamp in the specified timezone', () => {
const timestamp = '2025-02-28T12:00:00.000';
const timezone = 'Europe/Kiev';
const seconds = 10;
const expected = new Date('2025-02-28T12:00:10.000');

expect(addSecondsToLocalTimestamp(timestamp, timezone, seconds)).toEqual(expected);
});

it('should correctly add seconds to a timestamp with UTC timezone', () => {
const timestamp = '2025-02-28T12:00:00.000Z';
const timezone = 'Europe/Kiev';
const seconds = 60;
const expected = new Date('2025-02-28T14:01:00.000');

expect(addSecondsToLocalTimestamp(timestamp, timezone, seconds)).toEqual(expected);
});

it('should correctly add seconds to a timestamp without milliseconds', () => {
const timestamp = '2025-02-28T12:00:00';
const timezone = 'Europe/Kiev';
const seconds = 30;
const expected = new Date('2025-02-28T12:00:30.000');

expect(addSecondsToLocalTimestamp(timestamp, timezone, seconds)).toEqual(expected);
});

it('should correctly handle timestamp with microseconds and add seconds', () => {
const timestamp = '2025-02-28T12:00:00.123456Z';
const timezone = 'Europe/Kiev';
const seconds = 60;
const expected = new Date('2025-02-28T14:01:00.123456');

expect(addSecondsToLocalTimestamp(timestamp, timezone, seconds)).toEqual(expected);
});

it('should correctly add seconds to timestamp with long format', () => {
const timestamp = '2025-02-28T12:00:00.000';
const timezone = 'Europe/Kiev';
const seconds = 100;
const expected = new Date('2025-02-28T12:01:40.000');

expect(addSecondsToLocalTimestamp(timestamp, timezone, seconds)).toEqual(expected);
});

it('should return the same time if seconds to add is 0', () => {
const timestamp = '2025-02-28T12:00:00.000';
const timezone = 'Europe/Kiev';
const seconds = 0;
const expected = new Date('2025-02-28T12:00:00.000');

expect(addSecondsToLocalTimestamp(timestamp, timezone, seconds)).toEqual(expected);
});
});

describe('reformatInIsoLocal', () => {
it('should return the same timestamp if its length is 23 characters', () => {
const timestamp = '2025-02-28T12:00:00.000';
const expected = '2025-02-28T12:00:00.000';

expect(reformatInIsoLocal(timestamp)).toBe(expected);
});

it('should return timestamp without the "Z" if its length is 24 characters', () => {
const timestamp = '2025-02-28T12:00:00.000Z';
const expected = '2025-02-28T12:00:00.000';

expect(reformatInIsoLocal(timestamp)).toBe(expected);
});

it('should reformat timestamp in UTC to ISO 8601 local format', () => {
const timestamp = '2025-02-28T12:00:00';
const expected = '2025-02-28T12:00:00.000';

expect(reformatInIsoLocal(timestamp)).toBe(expected);
});

it('should return the same timestamp if it is an empty string', () => {
const timestamp = '';
const expected = '';

expect(reformatInIsoLocal(timestamp)).toBe(expected);
});
});

0 comments on commit 0037104

Please sign in to comment.