Skip to content

Commit

Permalink
Add Duration to Sampling Period UI Table (#1414)
Browse files Browse the repository at this point in the history
- formatTimeDifference function
  • Loading branch information
LouisThedroux authored Nov 12, 2024
1 parent 1ab1e64 commit 5203f31
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { StyledDataGrid } from 'components/data-grid/StyledDataGrid';
import { DATE_FORMAT } from 'constants/dateTimeFormats';
import dayjs from 'dayjs';
import { useCodesContext } from 'hooks/useContext';
import { formatTimeDifference } from 'utils/datetime';
import { getCodesName } from 'utils/Utils';

export interface ISamplingSitePeriodRowData {
Expand Down Expand Up @@ -82,6 +83,15 @@ export const SamplingPeriodTable = (props: ISamplingPeriodTableProps) => {
field: 'end_time',
headerName: 'End time',
flex: 1
},
{
field: 'duration',
headerName: 'Duration',
flex: 1,
renderCell: (params) => {
const { start_date, start_time, end_date, end_time } = params.row;
return formatTimeDifference(start_date, start_time, end_date, end_time);
}
}
];

Expand Down
53 changes: 53 additions & 0 deletions app/src/utils/datetime.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { combineDateTime, formatTimeDifference } from './datetime';

describe('combineDateTime', () => {
it('combines date and time into an ISO string', () => {
const result = combineDateTime('2024-01-01', '12:30:00');
expect(result).toEqual('2024-01-01T12:30:00.000Z');
});

it('combines date without time into an ISO string', () => {
const result = combineDateTime('2024-01-01');
expect(result).toEqual('2024-01-01T00:00:00.000Z');
});

it('returns ISO string for a different date and time', () => {
const result = combineDateTime('2023-12-31', '23:59:59');
expect(result).toEqual('2023-12-31T23:59:59.000Z');
});

it('handles invalid date formats gracefully', () => {
const date = combineDateTime('badDate', '12:00');
expect(date).toEqual('Invalid Date');

const time = combineDateTime('2024-01-01', 'badtime');
expect(time).toEqual('Invalid Date');
});
});

describe('formatTimeDifference', () => {
it('formats the time difference correctly between two dates and times', () => {
const result = formatTimeDifference('2024-01-01', '12:00', '2024-01-02', '13:30');
expect(result).toEqual('1 day and 1 hour');
});

it('handles time difference with only dates', () => {
const result = formatTimeDifference('2024-01-01', null, '2024-01-03', null);
expect(result).toEqual('2 days');
});

it('formats the time difference correctly with no time component', () => {
const result = formatTimeDifference('2024-01-01', null, '2024-01-01', '01:00');
expect(result).toEqual('1 hour');
});

it('returns null when there is no time difference', () => {
const result = formatTimeDifference('2024-01-01', null, '2024-01-01', null);
expect(result).toBeNull();
});

it('handles cases with invalid inputs', () => {
const result = formatTimeDifference('invalid-date', null, '2024-01-01', null);
expect(result).toBeNull();
});
});
55 changes: 53 additions & 2 deletions app/src/utils/datetime.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import { pluralize } from './Utils';

const TIMESTAMP_FORMAT = 'YYYY-MM-DDTHH:mm:ss.SSS[Z]';

dayjs.extend(duration);

/**
* Combine date and time and return ISO string.
*
Expand All @@ -7,7 +15,50 @@
*/
export const combineDateTime = (date: string, time?: string | null) => {
if (date && time) {
return new Date(`${date}T${time}`).toISOString();
return dayjs(`${date} ${time}`).format(TIMESTAMP_FORMAT);
}
return new Date(`${date}T00:00:00`).toISOString();

return dayjs(`${date}`).format(TIMESTAMP_FORMAT);
};

/**
* Formats the time difference between two timestamps into a human-readable string.
*
* @param {string} startDate
* @param {string | null} startTime
* @param {string} endDate
* @param {string | null} endTime
* @returns {string | null} A formatted string indicating an amount of time
*/
export const formatTimeDifference = (
startDate: string,
startTime: string | null,
endDate: string,
endTime: string | null
): string | null => {
const startDateTime = startTime ? dayjs(`${startDate} ${startTime}`) : dayjs(startDate);
const endDateTime = endTime ? dayjs(`${endDate} ${endTime}`) : dayjs(endDate);

if (!startDateTime.isValid() || !endDateTime.isValid()) {
return null;
}

// Calculate the total difference
const diff = dayjs.duration(endDateTime.diff(startDateTime));

const parts = [];

for (const unit of ['year', 'month', 'day', 'hour', 'minute', 'second']) {
const value = diff[`${unit}s`]();

if (value > 0) {
parts.push(`${value} ${pluralize(value, unit)}`);
}
}

if (!parts.length) {
return null;
}

return parts.slice(0, 2).join(' and ');
};

0 comments on commit 5203f31

Please sign in to comment.