Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import {
isBefore,
isSameDay,
isSameYear,
isValid,
setDefaultOptions,
startOfWeek,
subDays,
subMilliseconds,
subMinutes,
} from 'date-fns';
import {formatInTimeZone, utcToZonedTime, zonedTimeToUtc} from 'date-fns-tz';
import {formatInTimeZone, format as tzFormat, utcToZonedTime, zonedTimeToUtc} from 'date-fns-tz';
import {enGB, es} from 'date-fns/locale';
import throttle from 'lodash/throttle';
import Onyx from 'react-native-onyx';
Expand Down Expand Up @@ -335,6 +336,22 @@ function getStatusUntilDate(inputDate: string): string {
return translateLocal('statusPage.untilTime', {time: format(input, `${CONST.DATE.FNS_FORMAT_STRING} ${CONST.DATE.LOCAL_TIME_FORMAT}`)});
}

/**
* Get a date and format this date using the UTC timezone.
* @param datetime
* @param dateFormat
* @returns If the date is valid, returns the formatted date with the UTC timezone, otherwise returns an empty string.
*/
function formatWithUTCTimeZone(datetime: string, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING) {
const date = new Date(datetime);

if (isValid(date)) {
return tzFormat(utcToZonedTime(date, 'UTC'), dateFormat);
}

return '';
}

const DateUtils = {
formatToDayOfWeek,
formatToLongDateWithWeekday,
Expand All @@ -356,6 +373,7 @@ const DateUtils = {
isToday,
isTomorrow,
isYesterday,
formatWithUTCTimeZone,
};

export default DateUtils;
7 changes: 1 addition & 6 deletions src/libs/TransactionUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {format, isValid} from 'date-fns';
import Onyx, {OnyxCollection} from 'react-native-onyx';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -310,12 +309,8 @@ function getTag(transaction: Transaction): string {
*/
function getCreated(transaction: Transaction, dateFormat: string = CONST.DATE.FNS_FORMAT_STRING): string {
const created = transaction?.modifiedCreated ? transaction.modifiedCreated : transaction?.created || '';
const createdDate = new Date(created);
if (isValid(createdDate)) {
return format(createdDate, dateFormat);
}

return '';
return DateUtils.formatWithUTCTimeZone(created, dateFormat);
}

function isDistanceRequest(transaction: Transaction): boolean {
Expand Down
26 changes: 26 additions & 0 deletions tests/unit/DateUtilsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,30 @@ describe('DateUtils', () => {
expect(getDBTime).toBe('2022-11-22 03:14:10.792');
});
});

describe('formatWithUTCTimeZone', () => {
describe('when the date is invalid', () => {
it('returns an empty string', () => {
const invalidDateStr = '';

const formattedDate = DateUtils.formatWithUTCTimeZone(invalidDateStr);

expect(formattedDate).toEqual('');
});
});

describe('when the date is valid', () => {
const scenarios = [
{dateFormat: CONST.DATE.FNS_FORMAT_STRING, expectedResult: '2022-11-07'},
{dateFormat: CONST.DATE.FNS_TIMEZONE_FORMAT_STRING, expectedResult: '2022-11-07T00:00:00Z'},
{dateFormat: CONST.DATE.FNS_DB_FORMAT_STRING, expectedResult: '2022-11-07 00:00:00.000'},
];

test.each(scenarios)('returns the date as string with the format "$dateFormat"', ({dateFormat, expectedResult}) => {
const formattedDate = DateUtils.formatWithUTCTimeZone(datetime, dateFormat);

expect(formattedDate).toEqual(expectedResult);
});
});
});
});
64 changes: 64 additions & 0 deletions tests/unit/TransactionUtilsTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as TransactionUtils from '../../src/libs/TransactionUtils';
import type {Transaction} from '../../src/types/onyx';

function generateTransaction(values: Partial<Transaction> = {}): Transaction {
const reportID = '1';
const amount = 100;
const currency = 'USD';
const comment = '';
const created = '2023-10-01';
const baseValues = TransactionUtils.buildOptimisticTransaction(amount, currency, reportID, comment, created);

return {...baseValues, ...values};
}

describe('TransactionUtils', () => {
describe('getCreated', () => {
describe('when the transaction property "modifiedCreated" has value', () => {
const transaction = generateTransaction({
created: '2023-10-01',
modifiedCreated: '2023-10-25',
});

it('returns the "modifiedCreated" date with the correct format', () => {
const expectedResult = '2023-10-25';

const result = TransactionUtils.getCreated(transaction);

expect(result).toEqual(expectedResult);
});
});

describe('when the transaction property "modifiedCreated" does not have value', () => {
describe('and the transaction property "created" has value', () => {
const transaction = generateTransaction({
created: '2023-10-01',
modifiedCreated: undefined,
});

it('returns the "created" date with the correct format', () => {
const expectedResult = '2023-10-01';

const result = TransactionUtils.getCreated(transaction);

expect(result).toEqual(expectedResult);
});
});

describe('and the transaction property "created" does not have value', () => {
const transaction = generateTransaction({
created: undefined,
modifiedCreated: undefined,
});

it('returns an empty string', () => {
const expectedResult = '';

const result = TransactionUtils.getCreated(transaction);

expect(result).toEqual(expectedResult);
});
});
});
});
});