From 36318a05e3ba424e6cb0daa103921640ff06a2e8 Mon Sep 17 00:00:00 2001 From: Amith211 Date: Sat, 13 Nov 2021 16:02:31 +0000 Subject: [PATCH 1/5] add en-gb datetime overrides close #333 --- babybuddy/middleware.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/babybuddy/middleware.py b/babybuddy/middleware.py index a00b72c7..31c92157 100644 --- a/babybuddy/middleware.py +++ b/babybuddy/middleware.py @@ -5,6 +5,7 @@ import pytz from django.conf import settings from django.utils import timezone from django.conf.locale.en import formats as formats_en_us +from django.conf.locale.en_GB import formats as formats_en_gb def update_en_us_date_formats(): @@ -38,6 +39,32 @@ def update_en_us_date_formats(): custom_input_formats + formats_en_us.DATETIME_INPUT_FORMATS +def update_en_gb_date_formats(): + if settings.USE_24_HOUR_TIME_FORMAT: + formats_en_gb.DATETIME_FORMAT = 'j F Y H:i:s' + custom_input_formats = [ + '%d/%m/%Y %H:%M:%S', # '25/10/2006 14:30:59' + '%d/%m/%Y %H:%M', # '25/10/2006 14:30' + ] + formats_en_gb.SHORT_DATETIME_FORMAT = 'd/m/Y H:i' + formats_en_gb.TIME_FORMAT = 'H:i' + else: + # These formats are added to support the locale style of Baby Buddy's + # frontend library, which uses momentjs. + custom_input_formats = [ + '%d/%m/%Y %I:%M:%S %p', # '25/10/2006 2:30:59 PM' + '%d/%m/%Y %I:%M %p', # '25/10/2006 2:30 PM' + ] + + # Not setting this makes pages display using the the 25/10/2006 as desired + # Add custom "short" version of `MONTH_DAY_FORMAT`. + # formats_en_gb.SHORT_MONTH_DAY_FORMAT = 'j M' + + # Append all other input formats from the base locale. + formats_en_gb.DATETIME_INPUT_FORMATS = \ + custom_input_formats + formats_en_gb.DATETIME_INPUT_FORMATS + + class UserLanguageMiddleware: """ Customizes settings based on user language setting. @@ -49,7 +76,8 @@ class UserLanguageMiddleware: user = request.user if hasattr(user, 'settings') and user.settings.language == 'en-US': update_en_us_date_formats() - + elif hasattr(user, 'settings') and user.settings.language == 'en-GB': + update_en_gb_date_formats() return self.get_response(request) From 0312a4210d07618755b6ad9caf49b144e7bec58c Mon Sep 17 00:00:00 2001 From: Amith211 Date: Sun, 14 Nov 2021 01:20:20 +0000 Subject: [PATCH 2/5] add en-gb format tests --- babybuddy/tests/formats/tests_en_gb.py | 74 ++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 babybuddy/tests/formats/tests_en_gb.py diff --git a/babybuddy/tests/formats/tests_en_gb.py b/babybuddy/tests/formats/tests_en_gb.py new file mode 100644 index 00000000..639eb3ea --- /dev/null +++ b/babybuddy/tests/formats/tests_en_gb.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +import datetime + +from django.core.exceptions import ValidationError +from django.forms.fields import DateTimeField +from django.test import TestCase, override_settings, tag +from django.utils.formats import date_format, time_format + +from babybuddy.middleware import update_en_gb_date_formats + + +class GbFormatsTestCase(TestCase): + @override_settings(LANGUAGE_CODE='en-GB') + def test_datetime_input_formats(self): + update_en_gb_date_formats() + field = DateTimeField() + supported_custom_examples = [ + '20/01/2020', + '20/01/2020 9:30 AM', + '20/01/2020 9:30:03 AM', + '01/10/2020 11:30 PM', + '01/10/2020 11:30:03 AM', + ] + + for example in supported_custom_examples: + try: + result = field.to_python(example) + self.assertIsInstance(result, datetime.datetime) + except ValidationError: + self.fail('Format of "{}" not recognized!'.format(example)) + + with self.assertRaises(ValidationError): + field.to_python('invalid date string!') + + @tag('isolate') + @override_settings(LANGUAGE_CODE='en-GB', USE_24_HOUR_TIME_FORMAT=True) + def test_use_24_hour_time_format(self): + update_en_gb_date_formats() + field = DateTimeField() + supported_custom_examples = [ + '25/10/2006 2:30:59', + '25/10/2006 2:30', + '25/10/2006 14:30:59', + '25/10/2006 14:30', + ] + + for example in supported_custom_examples: + try: + result = field.to_python(example) + self.assertIsInstance(result, datetime.datetime) + except ValidationError: + self.fail('Format of "{}" not recognized!'.format(example)) + + with self.assertRaises(ValidationError): + field.to_python('invalid date string!') + + dt = datetime.datetime(year=2011, month=11, day=4, hour=23, minute=5, + second=59) + self.assertEqual( + date_format(dt, 'DATETIME_FORMAT'), '4 November 2011 23:05:59') + + dt = datetime.datetime(year=2011, month=11, day=4, hour=2, minute=5, + second=59) + self.assertEqual( + date_format(dt, 'SHORT_DATETIME_FORMAT'), '04/11//2011 2:05:59') + + t = datetime.time(hour=16, minute=2, second=25) + self.assertEqual(time_format(t), '16:02:25') + + # def test_short_month_day_format(self): + # update_en_gb_date_formats() + # dt = datetime.datetime(year=2021, month=7, day=31, hour=5, minute=5, + # second=5) + # self.assertEqual(date_format(dt, 'SHORT_MONTH_DAY_FORMAT'), '31 Jul') From df51cc05d873b9e1a45d59454eade825f5a11f66 Mon Sep 17 00:00:00 2001 From: Amith211 Date: Mon, 15 Nov 2021 16:56:59 +0000 Subject: [PATCH 3/5] fix en_GB tests --- babybuddy/tests/formats/tests_en_gb.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/babybuddy/tests/formats/tests_en_gb.py b/babybuddy/tests/formats/tests_en_gb.py index 639eb3ea..3f035250 100644 --- a/babybuddy/tests/formats/tests_en_gb.py +++ b/babybuddy/tests/formats/tests_en_gb.py @@ -3,7 +3,7 @@ import datetime from django.core.exceptions import ValidationError from django.forms.fields import DateTimeField -from django.test import TestCase, override_settings, tag +from django.test import TestCase, override_settings # , tag from django.utils.formats import date_format, time_format from babybuddy.middleware import update_en_gb_date_formats @@ -32,7 +32,7 @@ class GbFormatsTestCase(TestCase): with self.assertRaises(ValidationError): field.to_python('invalid date string!') - @tag('isolate') + # @tag('isolate') @override_settings(LANGUAGE_CODE='en-GB', USE_24_HOUR_TIME_FORMAT=True) def test_use_24_hour_time_format(self): update_en_gb_date_formats() @@ -62,10 +62,10 @@ class GbFormatsTestCase(TestCase): dt = datetime.datetime(year=2011, month=11, day=4, hour=2, minute=5, second=59) self.assertEqual( - date_format(dt, 'SHORT_DATETIME_FORMAT'), '04/11//2011 2:05:59') + date_format(dt, 'SHORT_DATETIME_FORMAT'), '04/11/2011 02:05') t = datetime.time(hour=16, minute=2, second=25) - self.assertEqual(time_format(t), '16:02:25') + self.assertEqual(time_format(t), '16:02') # def test_short_month_day_format(self): # update_en_gb_date_formats() From 429c85cd5a8b27755d0e3d7a7f1d63547e690ca5 Mon Sep 17 00:00:00 2001 From: Amith211 Date: Mon, 15 Nov 2021 17:24:08 +0000 Subject: [PATCH 4/5] fix en_GB display format --- babybuddy/middleware.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/babybuddy/middleware.py b/babybuddy/middleware.py index 31c92157..4acde9c5 100644 --- a/babybuddy/middleware.py +++ b/babybuddy/middleware.py @@ -41,6 +41,7 @@ def update_en_us_date_formats(): def update_en_gb_date_formats(): if settings.USE_24_HOUR_TIME_FORMAT: + # 25 October 2006 14:30:00 formats_en_gb.DATETIME_FORMAT = 'j F Y H:i:s' custom_input_formats = [ '%d/%m/%Y %H:%M:%S', # '25/10/2006 14:30:59' @@ -49,6 +50,7 @@ def update_en_gb_date_formats(): formats_en_gb.SHORT_DATETIME_FORMAT = 'd/m/Y H:i' formats_en_gb.TIME_FORMAT = 'H:i' else: + formats_en_gb.DATETIME_FORMAT = 'j F Y f a' # 25 October 2006 2:30 p.m # These formats are added to support the locale style of Baby Buddy's # frontend library, which uses momentjs. custom_input_formats = [ From e13f00e024fe987f7ead9067a53ad8e3ce6b8aad Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Sun, 28 Nov 2021 15:51:51 -0500 Subject: [PATCH 5/5] Force AM/PM for en-GB 12H setting combination --- core/templatetags/datetime.py | 26 +++++++++++++++--- core/tests/tests_templatetags.py | 45 ++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/core/templatetags/datetime.py b/core/templatetags/datetime.py index 6114840e..f3d370fd 100644 --- a/core/templatetags/datetime.py +++ b/core/templatetags/datetime.py @@ -7,19 +7,37 @@ from django.utils.translation import gettext_lazy as _ register = template.Library() -@register.simple_tag() -def datetimepicker_format(format_string='L LT'): +@register.simple_tag(takes_context=True) +def datetimepicker_format(context, format_string='L LT'): """ Return a datetime format string for momentjs, with support for 24 hour time override setting. + :param context: caller context data :param format_string: the default format string (locale based) :return: the format string to use, as 24 hour time if configured. """ + try: + user = context['request'].user + if hasattr(user, 'settings') and user.settings.language: + language = user.settings.language + else: + language = settings.LANGUAGE_CODE + except KeyError: + language = None + if settings.USE_24_HOUR_TIME_FORMAT: if format_string == 'L LT': - return 'L HH:mm' + format_string = 'L HH:mm' elif format_string == 'L LTS': - return 'L HH:mm:ss' + format_string = 'L HH:mm:ss' + elif language and language == 'en-GB': + # Force 12-hour format if 24 hour format is not configured for en-GB + # (Django default is 12H, momentjs default is 24H). + if format_string == 'L LT': + format_string = 'L h:mm a' + elif format_string == 'L LTS': + format_string = 'L h:mm:ss a' + return format_string diff --git a/core/tests/tests_templatetags.py b/core/tests/tests_templatetags.py index d775160b..ec0e614f 100644 --- a/core/tests/tests_templatetags.py +++ b/core/tests/tests_templatetags.py @@ -1,12 +1,17 @@ # -*- coding: utf-8 -*- from django.contrib.auth.models import User -from django.test import TestCase +from django.test import TestCase, override_settings from django.utils import timezone, formats from core.models import Child, Timer from core.templatetags import bootstrap, datetime, duration, timers +class MockUserRequest: + def __init__(self, user): + self.user = user + + class TemplateTagsTestCase(TestCase): def test_bootstrap_bool_icon(self): self.assertEqual( @@ -72,17 +77,41 @@ class TemplateTagsTestCase(TestCase): timer.id, child.slug)) def test_datetimepicker_format(self): - self.assertEqual(datetime.datetimepicker_format(), 'L LT') - self.assertEqual(datetime.datetimepicker_format('L LT'), 'L LT') - self.assertEqual( - datetime.datetimepicker_format('L LTS'), 'L LTS') + request = MockUserRequest(User.objects.first()) + request.user.settings.dashboard_hide_empty = True + context = {'request': request} + + with self.settings(USE_24_HOUR_TIME_FORMAT=False): + self.assertEqual(datetime.datetimepicker_format(context), 'L LT') + self.assertEqual( + datetime.datetimepicker_format(context, 'L LT'), 'L LT') + self.assertEqual( + datetime.datetimepicker_format(context, 'L LTS'), 'L LTS') with self.settings(USE_24_HOUR_TIME_FORMAT=True): - self.assertEqual(datetime.datetimepicker_format(), 'L HH:mm') self.assertEqual( - datetime.datetimepicker_format('L LT'), 'L HH:mm') + datetime.datetimepicker_format(context), 'L HH:mm') self.assertEqual( - datetime.datetimepicker_format('L LTS'), 'L HH:mm:ss') + datetime.datetimepicker_format(context, 'L LT'), 'L HH:mm') + self.assertEqual( + datetime.datetimepicker_format(context, 'L LTS'), 'L HH:mm:ss') + + @override_settings(USE_24_HOUR_TIME_FORMAT=False) + def test_datetimepicker_format_en_gb(self): + user = User.objects.first() + user.settings.language = 'en-GB' + user.save() + + request = MockUserRequest(user) + request.user.settings.dashboard_hide_empty = True + context = {'request': request} + + self.assertEqual( + datetime.datetimepicker_format(context), 'L h:mm a') + self.assertEqual( + datetime.datetimepicker_format(context, 'L LT'), 'L h:mm a') + self.assertEqual( + datetime.datetimepicker_format(context, 'L LTS'), 'L h:mm:ss a') def test_datetime_short(self): date = timezone.localtime()