Repository: jama5262/jiffy

Issue:
Locale Code Formatting and Validation Bug (Prepare for major version 7.x.x)
## Describe the Bug  

In version `6.x.x`, setting the locale code is not straightforward, and we currently do not verify the provided locale code.  

For example, `en-US` is a commonly used format but does not match the expected format of the `Intl` package. However, it is still valid—we just need to normalize it to the correct format: `language_country` (e.g., `en_US` with an underscore).  

We need to ensure that the following variations are correctly verified and accepted:  

- `language-country` (e.g., `en-US`)  
- `language-country` (e.g., `en-us`)  
- `language_country` (e.g., `en_US`)  
- `language_country` (e.g., `en_us`)  
- `language_country` (e.g., `EN_US`)  
- `language` only (e.g., `en`)  

---

## Expected Behavior  

The system should validate the provided locale formats, normalize them into a valid format, and check if they exist in the `Intl` package’s list of supported locales.


**Screenshots**

If applicable, add screenshots to help explain your problem.

**Additional information**

Add any additional information that you think may be relevant about the problem here.




Fix patch:
diff --git a/lib/src/global/global_ordinals.dart b/lib/src/global/global_ordinals.dart
index 93c0e976..0dd47f66 100644
--- a/lib/src/global/global_ordinals.dart
+++ b/lib/src/global/global_ordinals.dart
@@ -1,7 +1,5 @@
-import 'package:intl/intl.dart';
-
+import '../utils/verify_locale.dart';
 import '../locale/ordinals.dart';
-import '../utils/jiffy_exception.dart';
 
 Map<String, Ordinals> _builtInOrdinals = {
   'en': Ordinals(first: 'st', second: 'nd', third: 'rd', nth: 'th'),
@@ -42,10 +40,15 @@ Ordinals getOrdinals(String locale) {
   if (_defaultOrdinals != null) {
     return _defaultOrdinals!;
   } else {
-    final ordinals = _builtInOrdinals[Intl.shortLocale(locale)];
-    if (ordinals == null) {
-      throw JiffyException("Locale `$locale` is not supported for ordinals.");
-    }
-    return ordinals;
+    final supportedLocale = verifyLocale(locale,
+        onLocaleExists: (localeExists) =>
+            _builtInOrdinals.containsKey(localeExists),
+        onFailureMessage: _onFailureMessageLocaleNotSupported);
+
+    return _builtInOrdinals[supportedLocale.NAME]!;
   }
 }
+
+String _onFailureMessageLocaleNotSupported(String locale) {
+  return "Locale `$locale` is not supported for ordinals.";
+}
diff --git a/lib/src/global/global_relative_date_time.dart b/lib/src/global/global_relative_date_time.dart
index b287c7dd..11d3e90b 100644
--- a/lib/src/global/global_relative_date_time.dart
+++ b/lib/src/global/global_relative_date_time.dart
@@ -1,7 +1,5 @@
-import 'package:intl/intl.dart';
-
+import '../utils/verify_locale.dart';
 import '../locale/relative_date_time.dart';
-import '../utils/jiffy_exception.dart';
 
 Map<String, RelativeDateTime> _relativeDateTime = {
   'en': EnRelativeDateTime(),
@@ -12,12 +10,7 @@ Map<String, RelativeDateTime> _relativeDateTime = {
   'de': DeRelativeDateTime(),
   'it': ItRelativeDateTime(),
   'ar': ArRelativeDateTime(true),
-  'ar_LY': ArRelativeDateTime(false),
   'ar_DZ': ArSaMaDzKwTnRelativeDateTime(false),
-  'ar_KW': ArSaMaDzKwTnRelativeDateTime(false),
-  'ar_SA': ArSaMaDzKwTnRelativeDateTime(true),
-  'ar_MA': ArSaMaDzKwTnRelativeDateTime(false),
-  'ar_TN': ArSaMaDzKwTnRelativeDateTime(false),
   'az': AzRelativeDateTime(),
   'id': IdRelativeDateTime(),
   'ja': JaRelativeDateTime(),
@@ -49,15 +42,15 @@ RelativeDateTime getRelativeDateTime(String locale) {
   if (_defaultRelativeDateTime != null) {
     return _defaultRelativeDateTime!;
   } else {
-    final canonicalizedLocale = Intl.canonicalizedLocale(locale);
-    final rdt1 = _relativeDateTime[canonicalizedLocale];
-    if (rdt1 != null) return rdt1;
-
-    final shortLocale = Intl.shortLocale(locale);
-    final rdt2 = _relativeDateTime[shortLocale];
-    if (rdt2 != null) return rdt2;
+    final supportedLocale = verifyLocale(locale,
+        onLocaleExists: (localeExists) =>
+            _relativeDateTime.containsKey(localeExists),
+        onFailureMessage: _onFailureMessageLocaleNotSupported);
 
-    throw JiffyException(
-        "Locale `$locale` is not supported for relative date formatting.");
+    return _relativeDateTime[supportedLocale.NAME]!;
   }
 }
+
+String _onFailureMessageLocaleNotSupported(String locale) {
+  return "Locale `$locale` is not supported for relative date time formatting.";
+}
diff --git a/lib/src/global/global_start_of_week.dart b/lib/src/global/global_start_of_week.dart
index 6b1b886e..3a3781e2 100644
--- a/lib/src/global/global_start_of_week.dart
+++ b/lib/src/global/global_start_of_week.dart
@@ -1,6 +1,5 @@
-import 'package:intl/date_symbol_data_local.dart' as date_intl;
-import 'package:jiffy/src/utils/jiffy_exception.dart';
-
+import '../utils/jiffy_exception.dart';
+import '../utils/verify_locale.dart';
 import '../enums/start_of_week.dart';
 
 StartOfWeek? _defaultStartOfWeek;
@@ -13,11 +12,7 @@ StartOfWeek getStartOfWeek(String locale) {
   if (_defaultStartOfWeek != null) {
     return _defaultStartOfWeek!;
   } else {
-    final supportedLocale = date_intl.dateTimeSymbolMap()[locale];
-
-    if (supportedLocale == null) {
-      throw JiffyException("The specified locale '$locale' is not supported.");
-    }
+    final supportedLocale = verifyLocale(locale);
 
     return switch (supportedLocale.FIRSTDAYOFWEEK) {
       0 => StartOfWeek.monday,
diff --git a/lib/src/jiffy.dart b/lib/src/jiffy.dart
index 6622cf44..8f2ce8d9 100644
--- a/lib/src/jiffy.dart
+++ b/lib/src/jiffy.dart
@@ -1,6 +1,7 @@
 import 'package:intl/intl.dart';
 import 'package:intl/date_symbol_data_local.dart' as date_intl;
 
+import './utils/verify_locale.dart';
 import './default_display.dart';
 import './display.dart';
 import './enums/start_of_week.dart';
@@ -65,18 +66,12 @@ class Jiffy {
     RelativeDateTime? relativeDateTime,
   }) async {
     try {
-      final supportedLocale = Intl.verifiedLocale(locale,
-          (localeExists) => getSupportedLocales().contains(localeExists));
-
-      if (supportedLocale != null) {
-        Intl.defaultLocale = locale;
-        await date_intl.initializeDateFormatting();
-        defaultStartOfWeek = startOfWeek;
-        defaultOrdinals = ordinals;
-        defaultRelativeDateTime = relativeDateTime;
-      } else {
-        throw JiffyException('The locale `$locale` is not supported');
-      }
+      final supportedLocale = verifyLocale(locale);
+      Intl.defaultLocale = supportedLocale.NAME;
+      await date_intl.initializeDateFormatting();
+      defaultStartOfWeek = startOfWeek;
+      defaultOrdinals = ordinals;
+      defaultRelativeDateTime = relativeDateTime;
     } on ArgumentError catch (e) {
       throw JiffyException(e.message);
     }
@@ -90,8 +85,7 @@ class Jiffy {
   /// final supportLocales = Jiffy.getSupportedLocales();
   /// print(supportLocales); // ['en_us', 'en', 'fr', ...]
   /// ```
-  static List<String> getSupportedLocales() =>
-      date_intl.dateTimeSymbolMap().keys.toList();
+  static List<String> getSupportedLocales() => getSupportedIntlLocales();
 
   /// Constructs a new [Jiffy] instance by parsing a [String].
   ///
diff --git a/lib/src/locale/relative_date_time.dart b/lib/src/locale/relative_date_time.dart
index ac750bfc..9e9c9696 100644
--- a/lib/src/locale/relative_date_time.dart
+++ b/lib/src/locale/relative_date_time.dart
@@ -1,6 +1,5 @@
 import 'package:quiver/core.dart';
 import '../../jiffy.dart';
-import '../utils/replace.dart';
 
 abstract class RelativeDateTime {
   String prefixAgo();
@@ -429,7 +428,7 @@ class ArRelativeDateTime extends RelativeDateTime {
     } else {
       result = '$minutes دقائق ';
     }
-    return replaceNum ? replaceToLocaleNum(result, 'ar') : result;
+    return replaceNum ? _replaceToLocaleNum(result, 'ar') : result;
   }
 
   @override
@@ -449,7 +448,7 @@ class ArRelativeDateTime extends RelativeDateTime {
     } else {
       result = '$hours ساعات ';
     }
-    return replaceNum ? replaceToLocaleNum(result, 'ar') : result;
+    return replaceNum ? _replaceToLocaleNum(result, 'ar') : result;
   }
 
   @override
@@ -469,7 +468,7 @@ class ArRelativeDateTime extends RelativeDateTime {
     } else {
       result = '$days ايام ';
     }
-    return replaceNum ? replaceToLocaleNum(result, 'ar') : result;
+    return replaceNum ? _replaceToLocaleNum(result, 'ar') : result;
   }
 
   @override
@@ -489,7 +488,7 @@ class ArRelativeDateTime extends RelativeDateTime {
     } else {
       result = '$months شهور ';
     }
-    return replaceNum ? replaceToLocaleNum(result, 'ar') : result;
+    return replaceNum ? _replaceToLocaleNum(result, 'ar') : result;
   }
 
   @override
@@ -509,7 +508,7 @@ class ArRelativeDateTime extends RelativeDateTime {
     } else {
       result = '$years أعوام ';
     }
-    return replaceNum ? replaceToLocaleNum(result, 'ar') : result;
+    return replaceNum ? _replaceToLocaleNum(result, 'ar') : result;
   }
 
   @override
@@ -542,7 +541,7 @@ class ArSaMaDzKwTnRelativeDateTime extends RelativeDateTime {
   @override
   String minutes(int minutes) {
     return replaceNum
-        ? replaceToLocaleNum('$minutes دقائق ', 'ar')
+        ? _replaceToLocaleNum('$minutes دقائق ', 'ar')
         : '$minutes دقائق ';
   }
 
@@ -552,7 +551,7 @@ class ArSaMaDzKwTnRelativeDateTime extends RelativeDateTime {
   @override
   String hours(int hours) {
     return replaceNum
-        ? replaceToLocaleNum('$hours ساعات ', 'ar')
+        ? _replaceToLocaleNum('$hours ساعات ', 'ar')
         : '$hours ساعات ';
   }
 
@@ -561,7 +560,9 @@ class ArSaMaDzKwTnRelativeDateTime extends RelativeDateTime {
 
   @override
   String days(int days) {
-    return replaceNum ? replaceToLocaleNum('$days أيام ', 'ar') : '$days أيام ';
+    return replaceNum
+        ? _replaceToLocaleNum('$days أيام ', 'ar')
+        : '$days أيام ';
   }
 
   @override
@@ -570,7 +571,7 @@ class ArSaMaDzKwTnRelativeDateTime extends RelativeDateTime {
   @override
   String months(int months) {
     return replaceNum
-        ? replaceToLocaleNum('$months أشهر ', 'ar')
+        ? _replaceToLocaleNum('$months أشهر ', 'ar')
         : '$months أشهر ';
   }
 
@@ -580,7 +581,7 @@ class ArSaMaDzKwTnRelativeDateTime extends RelativeDateTime {
   @override
   String years(int years) {
     return replaceNum
-        ? replaceToLocaleNum('$years سنوات ', 'ar')
+        ? _replaceToLocaleNum('$years سنوات ', 'ar')
         : '$years سنوات ';
   }
 
@@ -1447,7 +1448,7 @@ class FaRelativeDateTime extends RelativeDateTime {
   String minutes(int minutes) {
     String result;
     result = '$minutes دقیقه ';
-    return replaceToLocaleNum(result, 'fa');
+    return _replaceToLocaleNum(result, 'fa');
   }
 
   @override
@@ -1457,7 +1458,7 @@ class FaRelativeDateTime extends RelativeDateTime {
   String hours(int hours) {
     String result;
     result = '$hours ساعت ';
-    return replaceToLocaleNum(result, 'fa');
+    return _replaceToLocaleNum(result, 'fa');
   }
 
   @override
@@ -1467,7 +1468,7 @@ class FaRelativeDateTime extends RelativeDateTime {
   String days(int days) {
     String result;
     result = '$days روز ';
-    return replaceToLocaleNum(result, 'fa');
+    return _replaceToLocaleNum(result, 'fa');
   }
 
   @override
@@ -1477,7 +1478,7 @@ class FaRelativeDateTime extends RelativeDateTime {
   String months(int months) {
     String result;
     result = '$months ماه ';
-    return replaceToLocaleNum(result, 'fa');
+    return _replaceToLocaleNum(result, 'fa');
   }
 
   @override
@@ -1487,7 +1488,7 @@ class FaRelativeDateTime extends RelativeDateTime {
   String years(int years) {
     String result;
     result = '$years سال ';
-    return replaceToLocaleNum(result, 'fa');
+    return _replaceToLocaleNum(result, 'fa');
   }
 
   @override
@@ -1514,31 +1515,31 @@ class BnRelativeDateTime extends RelativeDateTime {
   String aboutAMinute(int minutes) => 'এক মিনিট';
 
   @override
-  String minutes(int minutes) => replaceToLocaleNum('$minutes মিনিট', 'bn');
+  String minutes(int minutes) => _replaceToLocaleNum('$minutes মিনিট', 'bn');
 
   @override
   String aboutAnHour(int minutes) => 'এক ঘন্টা';
 
   @override
-  String hours(int hours) => replaceToLocaleNum('$hours ঘন্টা', 'bn');
+  String hours(int hours) => _replaceToLocaleNum('$hours ঘন্টা', 'bn');
 
   @override
   String aDay(int hours) => 'এক দিন';
 
   @override
-  String days(int days) => replaceToLocaleNum('$days দিন', 'bn');
+  String days(int days) => _replaceToLocaleNum('$days দিন', 'bn');
 
   @override
   String aboutAMonth(int days) => 'এক মাস';
 
   @override
-  String months(int months) => replaceToLocaleNum('$months মাস', 'bn');
+  String months(int months) => _replaceToLocaleNum('$months মাস', 'bn');
 
   @override
   String aboutAYear(int year) => 'এক বছর';
 
   @override
-  String years(int years) => replaceToLocaleNum('$years বছর', 'bn');
+  String years(int years) => _replaceToLocaleNum('$years বছর', 'bn');
 
   @override
   String wordSeparator() => ' ';
@@ -1744,3 +1745,17 @@ class CsRelativeDateTime extends RelativeDateTime {
   @override
   String wordSeparator() => ' ';
 }
+
+String _replaceToLocaleNum(String input, String locale) {
+  var localeNumbers = {
+    'en': ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
+    'ar': ['۰', '۱', '۲', '۳', '٤', '۵', '٦', '۷', '۸', '۹'],
+    'fa': ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'],
+    'bn': ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯']
+  };
+  for (var i = 0; i < localeNumbers['en']!.length; i++) {
+    input =
+        input.replaceAll(localeNumbers['en']![i], localeNumbers[locale]![i]);
+  }
+  return input;
+}
diff --git a/lib/src/utils/replace.dart b/lib/src/utils/replace.dart
deleted file mode 100644
index 6c28ad05..00000000
--- a/lib/src/utils/replace.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-String replaceToLocaleNum(String input, String locale) {
-  var localeNumbers = {
-    'en': ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
-    'ar': ['۰', '۱', '۲', '۳', '٤', '۵', '٦', '۷', '۸', '۹'],
-    'fa': ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'],
-    'bn': ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯']
-  };
-  for (var i = 0; i < localeNumbers['en']!.length; i++) {
-    input =
-        input.replaceAll(localeNumbers['en']![i], localeNumbers[locale]![i]);
-  }
-  return input;
-}
diff --git a/lib/src/utils/verify_locale.dart b/lib/src/utils/verify_locale.dart
new file mode 100644
index 00000000..38a03598
--- /dev/null
+++ b/lib/src/utils/verify_locale.dart
@@ -0,0 +1,30 @@
+import 'package:intl/intl.dart';
+import 'package:intl/date_symbol_data_local.dart' as date_intl;
+import 'package:intl/date_symbols.dart';
+
+import 'jiffy_exception.dart';
+
+List<String> getSupportedIntlLocales() =>
+    date_intl.dateTimeSymbolMap().keys.toList();
+
+DateSymbols verifyLocale(String locale,
+    {bool Function(String)? onLocaleExists,
+    String Function(String)? onFailureMessage}) {
+  final failureMessage = onFailureMessage != null
+      ? onFailureMessage(locale)
+      : "The specified locale '$locale' is not supported.";
+
+  final supportedLocale = Intl.verifiedLocale(
+      locale, (onLocaleExists ?? _doesLocaleExist),
+      onFailure: (_) => _throwLocaleNotSupported(failureMessage))!;
+
+  return date_intl.dateTimeSymbolMap()[supportedLocale]!;
+}
+
+bool _doesLocaleExist(String locale) {
+  return getSupportedIntlLocales().contains(locale);
+}
+
+String _throwLocaleNotSupported(String message) {
+  throw JiffyException(message);
+}


Test patch:
diff --git a/test/src/global/global_ordinals_test.dart b/test/src/global/global_ordinals_test.dart
index e03727d4..9f1f3562 100644
--- a/test/src/global/global_ordinals_test.dart
+++ b/test/src/global/global_ordinals_test.dart
@@ -1,6 +1,7 @@
 import 'package:jiffy/src/global/global_ordinals.dart';
 import 'package:jiffy/src/locale/ordinals.dart';
 import 'package:jiffy/src/utils/jiffy_exception.dart';
+import 'package:jiffy/src/utils/verify_locale.dart';
 import 'package:test/test.dart';
 
 void main() {
@@ -80,6 +81,9 @@ void main() {
 
       // Execute & Verify
       for (var entry in locales.entries) {
+        // Verify that the ordinal locales also exist in Intl locales
+        expect(() => verifyLocale(entry.key), returnsNormally);
+
         expect(getOrdinals(entry.key), entry.value);
       }
     });
diff --git a/test/src/global/global_relative_date_time_test.dart b/test/src/global/global_relative_date_time_test.dart
index ac464875..8ce1b33e 100644
--- a/test/src/global/global_relative_date_time_test.dart
+++ b/test/src/global/global_relative_date_time_test.dart
@@ -1,6 +1,7 @@
 import 'package:jiffy/src/global/global_relative_date_time.dart';
 import 'package:jiffy/src/locale/relative_date_time.dart';
 import 'package:jiffy/src/utils/jiffy_exception.dart';
+import 'package:jiffy/src/utils/verify_locale.dart';
 import 'package:test/test.dart';
 
 void main() {
@@ -21,24 +22,17 @@ void main() {
       expect(result, mockRdt);
     });
 
-    test('Should return RelativeDateTime for supported locale (canonicalized)',
-        () {
-      // Execute
-      final result = getRelativeDateTime('zh_CN');
-
-      // Verify
-      expect(result, isA<ZhCnRelativeDateTime>());
-    });
+    for (var testData in canonicalizedAndShortLocales()) {
+      test('Should return RelativeDateTime for supported locale', () {
+        // Execute
+        final result = getRelativeDateTime(testData['locale']);
 
-    test('Should return RelativeDateTime for supported locale (short)', () {
-      // Execute
-      final result = getRelativeDateTime('zh_CH');
+        // Verify
+        expect(result, equals(testData['expectedRelativeDateTime']));
+      });
+    }
 
-      // Verify
-      expect(result, isA<ZhRelativeDateTime>());
-    });
-
-    test('Should return RelativeDateTime for specific locale', () {
+    test('Should return RelativeDateTime for pre set locales', () {
       // Setup
       final relativeDateTimes = {
         'en': EnRelativeDateTime(),
@@ -49,12 +43,7 @@ void main() {
         'de': DeRelativeDateTime(),
         'it': ItRelativeDateTime(),
         'ar': ArRelativeDateTime(true),
-        'ar_LY': ArRelativeDateTime(false),
         'ar_DZ': ArSaMaDzKwTnRelativeDateTime(false),
-        'ar_KW': ArSaMaDzKwTnRelativeDateTime(false),
-        'ar_SA': ArSaMaDzKwTnRelativeDateTime(true),
-        'ar_MA': ArSaMaDzKwTnRelativeDateTime(false),
-        'ar_TN': ArSaMaDzKwTnRelativeDateTime(false),
         'az': AzRelativeDateTime(),
         'id': IdRelativeDateTime(),
         'ja': JaRelativeDateTime(),
@@ -78,6 +67,9 @@ void main() {
 
       // Execute & Verify
       for (var entry in relativeDateTimes.entries) {
+        // Verify that the relative date time locales also exist in Intl locales
+        expect(() => verifyLocale(entry.key), returnsNormally);
+
         expect(getRelativeDateTime(entry.key), entry.value);
       }
     });
@@ -93,11 +85,21 @@ void main() {
               (e) => e.toString(),
               'message',
               contains(
-                  "Locale `$unsupportedLocale` is not supported for relative date formatting."))));
+                  "Locale `$unsupportedLocale` is not supported for relative date time formatting."))));
     });
   });
 }
 
+List<Map<String, dynamic>> canonicalizedAndShortLocales() {
+  return [
+    {'locale': 'en', 'expectedRelativeDateTime': EnRelativeDateTime()},
+    {'locale': 'en_us', 'expectedRelativeDateTime': EnRelativeDateTime()},
+    {'locale': 'en-US', 'expectedRelativeDateTime': EnRelativeDateTime()},
+    {'locale': 'en_US', 'expectedRelativeDateTime': EnRelativeDateTime()},
+    {'locale': 'en_XYZ', 'expectedRelativeDateTime': EnRelativeDateTime()}
+  ];
+}
+
 class MockRelativeDateTime extends EnRelativeDateTime {
   String fromNow(DateTime dateTime) => "Mock fromNow";
 
diff --git a/test/src/jiffy_test.dart b/test/src/jiffy_test.dart
index 3a64a3e0..9eaeb08a 100644
--- a/test/src/jiffy_test.dart
+++ b/test/src/jiffy_test.dart
@@ -309,8 +309,9 @@ void main() {
 
     test('Should throw Jiffy exception if locale is not supported', () async {
       // Setup
-      final unknownLocaleCode = 'unknown_locale';
-      final expectedExceptionMessage = 'Invalid locale "$unknownLocaleCode"';
+      final unknownLocaleCode = "unknown_locale";
+      final expectedExceptionMessage =
+          "The specified locale '$unknownLocaleCode' is not supported.";
 
       // Execute and Verify
       expect(
diff --git a/test/src/utils/verify_locale_test.dart b/test/src/utils/verify_locale_test.dart
new file mode 100644
index 00000000..0e11d810
--- /dev/null
+++ b/test/src/utils/verify_locale_test.dart
@@ -0,0 +1,99 @@
+import 'package:intl/date_symbol_data_local.dart' as date_intl;
+import 'package:jiffy/src/utils/jiffy_exception.dart';
+import 'package:jiffy/src/utils/verify_locale.dart';
+import 'package:test/expect.dart';
+import 'package:test/scaffolding.dart';
+
+void main() {
+  test('Should successfully get a list of supported Intl locales', () {
+    // Setup
+    final intlLocales = date_intl.dateTimeSymbolMap().keys;
+
+    // Execute
+    final actualSupportedLocales = getSupportedIntlLocales();
+
+    // Verify
+    expect(actualSupportedLocales, intlLocales);
+  });
+
+  test(
+      'Should successfully verify and return a DateSymbol for supported locales',
+      () {
+    // Setup
+    final intlLocales = date_intl.dateTimeSymbolMap();
+
+    // Execute
+    for (var dateSymbol in intlLocales.values) {
+      expect(() => verifyLocale(dateSymbol.NAME), returnsNormally);
+      expect(verifyLocale(dateSymbol.NAME).serializeToMap(),
+          equals(dateSymbol.serializeToMap()));
+    }
+  });
+
+  test(
+      'Should successfully verify and accept different valid formated locale codes',
+      () {
+    // Setup
+    final locales = [
+      {'locale': 'en_US', 'expectedValidLocale': 'en_US'},
+      {'locale': 'en-US', 'expectedValidLocale': 'en_US'},
+      {'locale': 'en_us', 'expectedValidLocale': 'en_US'},
+      {'locale': 'en_US', 'expectedValidLocale': 'en_US'},
+      {'locale': 'EN-US', 'expectedValidLocale': 'en'},
+      {'locale': 'EN_US', 'expectedValidLocale': 'en'},
+      {'locale': 'EN_us', 'expectedValidLocale': 'en'},
+      {'locale': 'EN-us', 'expectedValidLocale': 'en'},
+      {'locale': 'en', 'expectedValidLocale': 'en'},
+      {'locale': 'EN', 'expectedValidLocale': 'en'}
+    ];
+
+    // Execute
+    for (var locale in locales) {
+      expect(verifyLocale(locale['locale']!).NAME,
+          equals(locale['expectedValidLocale']));
+    }
+  });
+
+  test('Should successfully verify from a list of custom supported locales',
+      () {
+    // Setup
+    final customIntlSupportedLocales = ['ar', 'ja', 'en_US'];
+
+    // Execute
+    for (var locale in customIntlSupportedLocales) {
+      expect(
+          verifyLocale(locale,
+              onLocaleExists: (locale) =>
+                  customIntlSupportedLocales.contains(locale)).NAME,
+          equals(locale));
+    }
+  });
+
+  test('Should throw exception if custom locales are not found intl', () {
+    // Setup
+    final customNoneIntlSupportedLocale = 'xyz';
+
+    // Execute and Verify
+    expect(
+        () => verifyLocale(customNoneIntlSupportedLocale),
+        throwsA(isA<JiffyException>().having(
+            (e) => e.toString(),
+            'message',
+            contains(
+                "The specified locale '$customNoneIntlSupportedLocale' is not supported."))));
+  });
+
+  test('Should successfully use custom failure function', () {
+    // Setup
+    final locale = 'unsupported_locale';
+    failureMessage(locale) =>
+        "This is a custom failure message, with locale $locale";
+    customerOnFailureMessage(locale) => failureMessage(locale);
+
+    // Execute and Verify
+    expect(
+        () => verifyLocale(locale, onFailureMessage: customerOnFailureMessage),
+        throwsA(isA<JiffyException>().having(
+            (e) => e.toString(), 'message', contains(failureMessage(locale)))));
+  });
+}