From e59f5c9af8d2ab7a887e5c3a86c67f080902e9b6 Mon Sep 17 00:00:00 2001
From: Julian Wachholz <julian@wachholz.ch>
Date: Tue, 9 Jul 2024 20:14:38 +0200
Subject: [PATCH] Add apostrophe-dot number format (#2982)

---
 packages/loot-core/src/shared/arithmetic.test.ts |  3 +++
 packages/loot-core/src/shared/arithmetic.ts      |  2 +-
 packages/loot-core/src/shared/util.test.ts       | 10 ++++++++++
 packages/loot-core/src/shared/util.ts            | 14 +++++++++++++-
 upcoming-release-notes/2982.md                   |  6 ++++++
 5 files changed, 33 insertions(+), 2 deletions(-)
 create mode 100644 upcoming-release-notes/2982.md

diff --git a/packages/loot-core/src/shared/arithmetic.test.ts b/packages/loot-core/src/shared/arithmetic.test.ts
index b897545dc..bb3eeb07d 100644
--- a/packages/loot-core/src/shared/arithmetic.test.ts
+++ b/packages/loot-core/src/shared/arithmetic.test.ts
@@ -44,5 +44,8 @@ describe('arithmetic', () => {
 
     setNumberFormat({ format: 'space-comma', hideFraction: false });
     expect(evalArithmetic('1\xa0222,45')).toEqual(1222.45);
+
+    setNumberFormat({ format: 'apostrophe-dot', hideFraction: false });
+    expect(evalArithmetic('1’222.45')).toEqual(1222.45);
   });
 });
diff --git a/packages/loot-core/src/shared/arithmetic.ts b/packages/loot-core/src/shared/arithmetic.ts
index bd4d26df8..0d595d1b7 100644
--- a/packages/loot-core/src/shared/arithmetic.ts
+++ b/packages/loot-core/src/shared/arithmetic.ts
@@ -38,7 +38,7 @@ function parsePrimary(state) {
   }
 
   let numberStr = '';
-  while (char(state) && char(state).match(/[0-9,.\xa0 ]|\p{Sc}/u)) {
+  while (char(state) && char(state).match(/[0-9,.’\xa0 ]|\p{Sc}/u)) {
     numberStr += next(state);
   }
 
diff --git a/packages/loot-core/src/shared/util.test.ts b/packages/loot-core/src/shared/util.test.ts
index ac2f2b70a..6f2be8a81 100644
--- a/packages/loot-core/src/shared/util.test.ts
+++ b/packages/loot-core/src/shared/util.test.ts
@@ -84,4 +84,14 @@ describe('utility functions', () => {
     formatter = getNumberFormat().formatter;
     expect(formatter.format(Number('1234.56'))).toBe('1\xa0235');
   });
+
+  test('number formatting works with apostrophe-dot format', () => {
+    setNumberFormat({ format: 'apostrophe-dot', hideFraction: false });
+    let formatter = getNumberFormat().formatter;
+    expect(formatter.format(Number('1234.56'))).toBe('1’234.56');
+
+    setNumberFormat({ format: 'apostrophe-dot', hideFraction: true });
+    formatter = getNumberFormat().formatter;
+    expect(formatter.format(Number('1234.56'))).toBe('1’235');
+  });
 });
diff --git a/packages/loot-core/src/shared/util.ts b/packages/loot-core/src/shared/util.ts
index cac3ff0bb..7a45a48f8 100644
--- a/packages/loot-core/src/shared/util.ts
+++ b/packages/loot-core/src/shared/util.ts
@@ -217,7 +217,12 @@ export function appendDecimals(
   return amountToCurrency(currencyToAmount(result));
 }
 
-type NumberFormats = 'comma-dot' | 'dot-comma' | 'space-comma' | 'comma-dot-in';
+type NumberFormats =
+  | 'comma-dot'
+  | 'dot-comma'
+  | 'space-comma'
+  | 'apostrophe-dot'
+  | 'comma-dot-in';
 
 export const numberFormats: Array<{
   value: NumberFormats;
@@ -227,6 +232,7 @@ export const numberFormats: Array<{
   { value: 'comma-dot', label: '1,000.33', labelNoFraction: '1,000' },
   { value: 'dot-comma', label: '1.000,33', labelNoFraction: '1.000' },
   { value: 'space-comma', label: '1\xa0000,33', labelNoFraction: '1\xa0000' },
+  { value: 'apostrophe-dot', label: '1’000.33', labelNoFraction: '1’000' },
   { value: 'comma-dot-in', label: '1,00,000.33', labelNoFraction: '1,00,000' },
 ];
 
@@ -263,6 +269,12 @@ export function getNumberFormat({
       regex = /[^-0-9,]/g;
       separator = ',';
       break;
+    case 'apostrophe-dot':
+      locale = 'de-CH';
+      regex = /[^-0-9,.]/g;
+      separator = '.';
+      separatorRegex = /[,.]/g;
+      break;
     case 'comma-dot-in':
       locale = 'en-IN';
       regex = /[^-0-9.]/g;
diff --git a/upcoming-release-notes/2982.md b/upcoming-release-notes/2982.md
new file mode 100644
index 000000000..2d6368342
--- /dev/null
+++ b/upcoming-release-notes/2982.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [julianwachholz]
+---
+
+Add apostrophe-dot (Swiss) number format
-- 
GitLab