diff --git a/src/components/Functions/Utils.mdx b/src/components/Functions/Utils.mdx
new file mode 100644
index 00000000..e7f13b23
--- /dev/null
+++ b/src/components/Functions/Utils.mdx
@@ -0,0 +1,16 @@
+import { Meta, Canvas } from '@storybook/blocks';
+
+import * as UtilFunctionStories from './Utils.stories.svelte';
+
+
+
+
+# Utils
+
+Utils TKTK
+
+
+```javascript
+import {prettifyDate} from '@reuters-graphics/graphics-components';
+
+```
\ No newline at end of file
diff --git a/src/components/Functions/Utils.stories.svelte b/src/components/Functions/Utils.stories.svelte
new file mode 100644
index 00000000..fe7b28a9
--- /dev/null
+++ b/src/components/Functions/Utils.stories.svelte
@@ -0,0 +1,9 @@
+
+
+
diff --git a/src/index.ts b/src/index.ts
index 35ad5ae4..790e9306 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,6 +2,9 @@
export { default as cssVariables } from './actions/cssVariables/index';
export { default as resizeObserver } from './actions/resizeObserver/index';
+// Utils
+export { prettifyDate } from './utils/index';
+
// Components
export {
default as Analytics,
diff --git a/src/test/utils.test.ts b/src/test/utils.test.ts
index 30f26910..3d120620 100644
--- a/src/test/utils.test.ts
+++ b/src/test/utils.test.ts
@@ -79,7 +79,7 @@ describe('Utils tests', () => {
const formattedMay = 'May';
expect(prettifyDate(unformattedMay)).toBe(formattedMay);
- const unformattedJune = 'Jun.';
+ const unformattedJune = 'JUN.';
const formattedJune = 'June';
expect(prettifyDate(unformattedJune)).toBe(formattedJune);
@@ -87,17 +87,17 @@ describe('Utils tests', () => {
const formattedJuly = 'July';
expect(prettifyDate(unformattedJuly)).toBe(formattedJuly);
- const unformattedSept = 'Sep.';
+ const unformattedSept = 'sep.';
const formattedSept = 'Sept.';
expect(prettifyDate(unformattedSept)).toBe(formattedSept);
});
it('should format months with year properly', () => {
- const unformattedMarch = 'Mar. 2025';
+ const unformattedMarch = 'MAR. 2025';
const formattedMarch = 'March 2025';
expect(prettifyDate(unformattedMarch)).toBe(formattedMarch);
- const unformattedApril = 'Apr. 2025';
+ const unformattedApril = 'apr. 2025';
const formattedApril = 'April 2025';
expect(prettifyDate(unformattedApril)).toBe(formattedApril);
@@ -136,6 +136,22 @@ describe('Utils tests', () => {
expect(prettifyDate(unformattedJune)).toBe(formattedJune);
});
+ it('should work with lower or upper case', () => {
+ const unformattedMarch = 'MAR. 1, 2023, 10:00pm';
+ const formattedMarch = 'March 1, 2023, 10:00 p.m.';
+ expect(prettifyDate(unformattedMarch)).toBe(formattedMarch);
+ const unformattedApril = 'APR. 1, 2023, 10:00AM';
+ const formattedApril = 'April 1, 2023, 10:00 a.m.';
+ expect(prettifyDate(unformattedApril)).toBe(formattedApril);
+
+ const unformattedMay = 'may. 1, 2023, 10:00am';
+ const formattedMay = 'May 1, 2023, 10:00 a.m.';
+ expect(prettifyDate(unformattedMay)).toBe(formattedMay);
+
+ const unformattedJune = 'JUN. 1, 2023, 10:00AM';
+ const formattedJune = 'June 1, 2023, 10:00 a.m.';
+ expect(prettifyDate(unformattedJune)).toBe(formattedJune);
+ });
});
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 5ad8d129..f854de2a 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -34,49 +34,50 @@ export const getAuthorPageUrl = (author: string): string => {
*
*/
export const prettifyDate = (input: string) => {
- // Define a object to map full month names to their Reuters style equivalents
+ // Define an object to map full month names to their Reuters style equivalents
const conversions: { [key: string]: string } = {
// full months
- January: 'Jan.',
- February: 'Feb.',
- August: 'Aug.',
- September: 'Sept.',
- October: 'Oct.',
- November: 'Nov.',
- December: 'Dec.',
+ january: 'Jan.',
+ february: 'Feb.',
+ august: 'Aug.',
+ september: 'Sept.',
+ october: 'Oct.',
+ november: 'Nov.',
+ december: 'Dec.',
// 3-letter abbreviations that need fixing
- Jan: 'Jan.',
- Feb: 'Feb.',
- Mar: 'March',
- Apr: 'April',
- Jun: 'June',
- Jul: 'July',
- Sep: 'Sept.',
+ jan: 'Jan.',
+ feb: 'Feb.',
+ mar: 'March',
+ apr: 'April',
+ jun: 'June',
+ jul: 'July',
+ sep: 'Sept.',
};
- // If the key in conversions is found in the input, replace it with the corresponding value
+ // If the key in conversions is found in the input (case insensitive), replace it with the corresponding value
let formatted = Object.keys(conversions).reduce((acc, key) => {
- const regex = new RegExp(`\\b${key}\\b`, 'g');
+ const regex = new RegExp(`\\b${key}\\b`, 'gi'); // Added 'i' flag for case insensitive
return acc.replace(regex, conversions[key]);
}, input);
- // Fix rogue periods in abbreviations
- let fixedAbbr = formatted.replace('Mar.', 'March')
- .replace('March.', 'March')
- .replace('Apr.', 'April')
- .replace('April.', 'April')
- .replace('May.', 'May')
- .replace('June.', 'June')
- .replace('July.', 'July')
- .replace('Sep.', 'Sept.');
+ // Fix rogue periods in abbreviations (case insensitive)
+ let fixedAbbr = formatted
+ .replace(/\bmar\./gi, 'March')
+ .replace(/\bmarch\./gi, 'March')
+ .replace(/\bapr\./gi, 'April')
+ .replace(/\bapril\./gi, 'April')
+ .replace(/\bmay\./gi, 'May')
+ .replace(/\bjune\./gi, 'June')
+ .replace(/\bjuly\./gi, 'July')
+ .replace(/\bsep\./gi, 'Sept.');
// Replace double periods with a single period
- let fixedPeriods = fixedAbbr.replace('..', '.');
+ let fixedPeriods = fixedAbbr.replace(/\.{2,}/g, '.');
- // Fix 'Mar. 1, 2023, 10:00pm' to 'March 1, 2023, 10:00 p.m.', with a space before 'p.m.'
- return prettifyAmPm(fixedPeriods)
-}
+ // Fix am/pm formatting
+ return prettifyAmPm(fixedPeriods);
+};
const prettifyAmPm = (text: string) => {
return text.replace(/(\d)\s*(am|AM|pm|PM)\b/g, (match, digit, timeDesignator) => {