[PATCH 1/2 v2] A function for resolving date format and order
Vratislav Podzimek
vpodzime at redhat.com
Thu Oct 9 08:49:19 UTC 2014
It's not that easy to get right order of date fields (year, month, day) and
their formats so we should better have it in a standalone function with tests.
Related: rhbz#1044233
Signed-off-by: Vratislav Podzimek <vpodzime at redhat.com>
---
pyanaconda/localization.py | 74 +++++++++++++++++++++++++++++
tests/pyanaconda_tests/localization_test.py | 21 ++++++++
2 files changed, 95 insertions(+)
diff --git a/pyanaconda/localization.py b/pyanaconda/localization.py
index c95fa1d..3011c84 100644
--- a/pyanaconda/localization.py
+++ b/pyanaconda/localization.py
@@ -26,6 +26,7 @@ import re
import langtable
import locale as locale_mod
import glob
+from collections import namedtuple
from pyanaconda import constants
from pyanaconda.iutil import upcase_first_letter
@@ -469,3 +470,76 @@ def load_firmware_language(lang):
log.debug("Using UEFI PlatformLang '%s' ('%s') as our language.", d, locales[0])
setup_locale(locales[0], lang)
+
+_DateFieldSpec = namedtuple("DateFieldSpec", ["format", "suffix"])
+
+def resolve_date_format(year, month, day, fail_safe=True):
+ """
+ Puts the year, month and day objects in the right order according to the
+ currently set locale and provides format specification for each of the
+ fields.
+
+ :param year: any object or value representing year
+ :type year: object
+ :param month: any object or value representing month
+ :type month: object
+ :param day: any object or value representing day
+ :type day: object
+ :param bool fail_safe: whether to fall back to default in case of invalid
+ format or raise exception instead
+ :returns: a pair where the first field contains a tuple with the year, month
+ and day objects/values put in the right order and where the second
+ field contains a tuple with three :class:`_DateFieldSpec` objects
+ specifying formats respectively to the first (year, month, day)
+ field
+ :rtype: tuple
+ :raise ValueError: in case currently set locale has unsupported date
+ format and fail_safe is set to False (likely a bug in
+ this function)
+
+ """
+
+ # see date (1), 'O' (not '0') is a mystery, 'E' is Buddhist calendar, '(.*)'
+ # is an arbitrary suffix
+ field_spec_re = re.compile(r'([-_0OE^#]*)([yYmbBde])(.*)')
+
+ order = []
+ formats = []
+ fmt_str = locale_mod.nl_langinfo(locale_mod.D_FMT)
+
+ if not fmt_str or "%" not in fmt_str:
+ if fail_safe:
+ # use some sane default
+ fmt_str = "%Y-%m-%d"
+ else:
+ raise ValueError("Invalid date format string for current locale: '%s'" % fmt_str)
+
+ # see date (1)
+ fmt_str = fmt_str.replace("%F", "%Y-%m-%d")
+
+ # e.g. "%d.%m.%Y" -> ['d.', 'm.', 'Y']
+ fields = fmt_str.split("%")[1:]
+
+ for field in fields:
+ match = field_spec_re.match(field)
+ if not match:
+ # ignore fields we are not interested in (like %A for weekday name, etc.)
+ continue
+
+ prefix, item, suffix = match.groups()
+ if item in ("d", "e"):
+ # "e" is the same as "_d"
+ order.append(day)
+ elif item in ("Y", "y"):
+ # 4-digit year, 2-digit year
+ order.append(year)
+ elif item in ("m", "b", "B"):
+ # month number, short month name, long month name
+ order.append(month)
+ else:
+ raise ValueError("Unsupported date format's '%s' field '%s'" % (fmt_str, field))
+
+ # "%" + prefix + item gives a format for date/time formatting functions
+ formats.append(_DateFieldSpec("%" + prefix + item, suffix.strip()))
+
+ return (tuple(order), tuple(formats))
diff --git a/tests/pyanaconda_tests/localization_test.py b/tests/pyanaconda_tests/localization_test.py
index 00ff31d..bd8ce00 100644
--- a/tests/pyanaconda_tests/localization_test.py
+++ b/tests/pyanaconda_tests/localization_test.py
@@ -19,6 +19,8 @@
#
from pyanaconda import localization
+from pyanaconda.iutil import execReadlines
+import locale as locale_mod
import unittest
class ParsingTests(unittest.TestCase):
@@ -139,3 +141,22 @@ class LangcodeLocaleMatchingTests(unittest.TestCase):
# no matches
self.assertIsNone(localization.find_best_locale_match("pt_BR", ["en_BR", "en"]))
self.assertIsNone(localization.find_best_locale_match("cs_CZ.UTF-8", ["en", "en.UTF-8"]))
+
+ def resolve_date_format_test(self):
+ """All locales' date formats should be properly resolved."""
+
+ locales = (line.strip() for line in execReadlines("locale", ["-a"]))
+ for locale in locales:
+ try:
+ locale_mod.setlocale(locale_mod.LC_ALL, locale)
+ except locale_mod.Error:
+ # cannot set locale (a bug in the locale module?)
+ continue
+
+ (order, formats) = localization.resolve_date_format(1, 2, 3, fail_safe=False)
+ if len(order) != 3:
+ self.fail("Not all date fields available for %s" % locale)
+ if len(formats) != 3:
+ self.fail("Not all date fields' formats available for %s" % locale)
+ for i in (1, 2, 3):
+ self.assertIn(i, order)
--
1.9.3
More information about the anaconda-patches
mailing list