diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TestSummaryCustomTooltip/TestSummaryCustomTooltip.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TestSummaryCustomTooltip/TestSummaryCustomTooltip.component.tsx index ca109743839..7218d1d097d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TestSummaryCustomTooltip/TestSummaryCustomTooltip.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TestSummaryCustomTooltip/TestSummaryCustomTooltip.component.tsx @@ -85,7 +85,13 @@ const TestSummaryCustomTooltip = ( {key === TABLE_FRESHNESS_KEY && isNumber(value) ? // freshness will always be in seconds, so we need to convert it to milliseconds - convertMillisecondsToHumanReadableFormat(value * 1000) + convertMillisecondsToHumanReadableFormat( + value * 1000, + undefined, + false, + // negative value will be shown as late by + `${t('label.late-by')} ` + ) : value} diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json index 72e564d4c12..541f9cebb7f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json @@ -766,6 +766,7 @@ "last-run": "Letzte Ausführung", "last-run-result": "Ergebnis der letzten Ausführung", "last-updated": "Zuletzt aktualisiert", + "late-by": "Late by", "latest": "Neueste", "latest-offset": "Neuester Offset", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json index 2dfdf41404f..2f40e65022b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json @@ -766,6 +766,7 @@ "last-run": "Last Run", "last-run-result": "Last Run Result", "last-updated": "Last Updated", + "late-by": "Late by", "latest": "Latest", "latest-offset": "Latest Offset", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json index d3beea92c92..76e4b56afce 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json @@ -766,6 +766,7 @@ "last-run": "Última ejecución", "last-run-result": "Último resultado de la ejecución", "last-updated": "Última actualización", + "late-by": "Tardío por", "latest": "Último", "latest-offset": "Último desplazamiento", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json index 8c42e798531..ab31ec24dee 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json @@ -766,6 +766,7 @@ "last-run": "Dernière Exécution", "last-run-result": "Résultat de la Dernière Exécution", "last-updated": "Dernière Mise à Jour", + "late-by": "En retard de", "latest": "Dernier·ère", "latest-offset": "Dernier décalage", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json index 002733898d3..35541ab18a6 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json @@ -766,6 +766,7 @@ "last-run": "Última execución", "last-run-result": "Resultado da última execución", "last-updated": "Última actualización", + "late-by": "Tardío por", "latest": "Último", "latest-offset": "Último desprazamento", "layer": "Capa", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json index 408d886f8e8..edd15b3c8a7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json @@ -766,6 +766,7 @@ "last-run": "הרצה אחרונה", "last-run-result": "תוצאת הרצה אחרונה", "last-updated": "עודכן לאחרונה", + "late-by": "מאחורי", "latest": "אחרון", "latest-offset": "היסט אחרון", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json index 5b9adfc5335..511787e779d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json @@ -766,6 +766,7 @@ "last-run": "Last Run", "last-run-result": "Last Run Result", "last-updated": "最終更新日", + "late-by": "遅れています", "latest": "最新", "latest-offset": "最新のオフセット", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json index 87b4cfcf508..572837c8363 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json @@ -766,6 +766,7 @@ "last-run": "마지막 실행", "last-run-result": "마지막 실행 결과", "last-updated": "마지막 업데이트", + "late-by": "지연됨", "latest": "최신", "latest-offset": "최신 오프셋", "layer": "계층", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json index be2e2d85d74..255d1fa5e6e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json @@ -766,6 +766,7 @@ "last-run": "शेवटची धाव", "last-run-result": "शेवटचा धाव परिणाम", "last-updated": "शेवटचे अद्यतनित", + "late-by": "विलंबाने", "latest": "नवीनतम", "latest-offset": "नवीनतम ऑफसेट", "layer": "स्तर", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json index 8962fc5a780..31b232854cf 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json @@ -766,6 +766,7 @@ "last-run": "Laatste uitvoering", "last-run-result": "Laatste uitvoerresultaat", "last-updated": "Laatst bijgewerkt", + "late-by": "Vooruitgang", "latest": "Laatste", "latest-offset": "Laatste offset", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json index 56e8c0c550e..51c1ba7a70c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json @@ -766,6 +766,7 @@ "last-run": "آخرین اجرا", "last-run-result": "نتیجه آخرین اجرا", "last-updated": "آخرین به‌روزرسانی", + "late-by": "تأخیر", "latest": "آخرین", "latest-offset": "آخرین آفست", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json index e4041368a39..18310601aad 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json @@ -766,6 +766,7 @@ "last-run": "Última Execução", "last-run-result": "Resultado da Última Execução", "last-updated": "Última Atualização", + "late-by": "Atrasado por", "latest": "Mais Recente", "latest-offset": "Último deslocamento", "layer": "Camada", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json index 01694b14eda..932458c2eb3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json @@ -766,6 +766,7 @@ "last-run": "Última Execução", "last-run-result": "Resultado da Última Execução", "last-updated": "Última Atualização", + "late-by": "Atrasado por", "latest": "Mais Recente", "latest-offset": "Latest Offset", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json index 2cde856c532..11b74e1d70c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json @@ -766,6 +766,7 @@ "last-run": "Последний запуск", "last-run-result": "Результат последнего запуска", "last-updated": "Последнее обновление", + "late-by": "Позже на", "latest": "Последний", "latest-offset": "Последнее смещение", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json index c57b8c9ff77..c6e8ce4a404 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json @@ -766,6 +766,7 @@ "last-run": "รันล่าสุด", "last-run-result": "ผลลัพธ์การรันล่าสุด", "last-updated": "อัปเดตล่าสุด", + "late-by": "ล่าช้า", "latest": "ล่าสุด", "latest-offset": "ออฟเซ็ตล่าสุด", "layer": "ชั้น", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json index 9ef8497132d..0ab2125808d 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json @@ -766,6 +766,7 @@ "last-run": "Son Çalışma", "last-run-result": "Son Çalışma Sonucu", "last-updated": "Son Güncelleme", + "late-by": "Gecikme", "latest": "En Son", "latest-offset": "En Son Ofset", "layer": "Katman", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json index 9e14ac14c89..3d35388564c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json @@ -766,6 +766,7 @@ "last-run": "最近运行", "last-run-result": "最近运行结果", "last-updated": "最近更新", + "late-by": "延迟", "latest": "最新", "latest-offset": "最新偏移量", "layer": "Layer", diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.test.ts b/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.test.ts index b32e85beac0..7322cd1d416 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.test.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.test.ts @@ -149,7 +149,7 @@ describe('convertMillisecondsToHumanReadableFormat', () => { { input: 3661000, expected: '1h 1m 1s' }, { input: 86400000, expected: '1d' }, { input: 90061000, expected: '1d 1h 1m 1s' }, - { input: -1000, expected: '0s' }, + { input: -1000, expected: '-1s' }, { input: 1200, expected: '1s 200ms', showMilliseconds: true }, { input: 90061560, @@ -158,19 +158,40 @@ describe('convertMillisecondsToHumanReadableFormat', () => { showMilliseconds: true, }, { input: 90061560, expected: '1d 1h', length: 2, showMilliseconds: true }, + { input: -61000, expected: '-1m 1s' }, + { + input: -3661000, + expected: 'Late by 1h 1m 1s', + prependForNegativeValue: 'Late by ', + }, + { input: -86400000, expected: '-1d' }, + { + input: -90061000, + expected: 'Late by 1d 1h 1m 1s', + prependForNegativeValue: 'Late by ', + }, ]; - testCases.forEach(({ input, expected, length, showMilliseconds }) => { - it(`should return "${expected}" for ${input} milliseconds`, () => { - expect( - convertMillisecondsToHumanReadableFormat( - input, - length, - showMilliseconds - ) - ).toBe(expected); - }); - }); + testCases.forEach( + ({ + input, + expected, + length, + showMilliseconds, + prependForNegativeValue, + }) => { + it(`should return "${expected}" for ${input} milliseconds`, () => { + expect( + convertMillisecondsToHumanReadableFormat( + input, + length, + showMilliseconds, + prependForNegativeValue + ) + ).toBe(expected); + }); + } + ); const testCasesWithLength = [ { diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.ts index 434c309b508..47010c46bda 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/date-time/DateTimeUtils.ts @@ -245,13 +245,22 @@ export const calculateInterval = ( export const convertMillisecondsToHumanReadableFormat = ( timestamp: number, length?: number, - showMilliseconds = false + showMilliseconds = false, + prependForNegativeValue = '-' ): string => { - if (timestamp <= 0 || (!showMilliseconds && timestamp < 1000)) { + // Handle zero and very small positive values + if ( + timestamp === 0 || + (!showMilliseconds && timestamp > 0 && timestamp < 1000) + ) { return '0s'; } - const duration = Duration.fromMillis(timestamp); + // Handle negative values + const isNegative = timestamp < 0; + const absoluteTimestamp = Math.abs(timestamp); + + const duration = Duration.fromMillis(absoluteTimestamp); const result: string[] = []; // Extract each unit from the duration @@ -286,11 +295,21 @@ export const convertMillisecondsToHumanReadableFormat = ( result.push(`${milliseconds}ms`); } - if (length && result.length > length) { - return result.slice(0, length).join(' '); + // If no units found, return 0s + if (result.length === 0) { + return '0s'; } - return result.join(' '); + let formattedResult = result.join(' '); + + if (length && result.length > length) { + formattedResult = result.slice(0, length).join(' '); + } + + // Prepend minus sign for negative values + return isNegative + ? `${prependForNegativeValue}${formattedResult}` + : formattedResult; }; export const formatDuration = (ms: number) => {