diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index 1500a05..3d1bff4 100644
a
|
b
|
def date(value, arg=None):
|
706 | 706 | arg = settings.DATE_FORMAT |
707 | 707 | try: |
708 | 708 | return formats.date_format(value, arg) |
709 | | except AttributeError: |
| 709 | except (AttributeError, UnicodeEncodeError): |
710 | 710 | try: |
711 | 711 | return format(value, arg) |
712 | 712 | except AttributeError: |
… |
… |
def time(value, arg=None):
|
722 | 722 | arg = settings.TIME_FORMAT |
723 | 723 | try: |
724 | 724 | return formats.time_format(value, arg) |
725 | | except AttributeError: |
| 725 | except (AttributeError, UnicodeEncodeError): |
726 | 726 | try: |
727 | 727 | return dateformat.time_format(value, arg) |
728 | 728 | except AttributeError: |
diff --git a/django/utils/encoding.py b/django/utils/encoding.py
index e2d7249..9301419 100644
a
|
b
|
def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):
|
58 | 58 | |
59 | 59 | If strings_only is True, don't convert (some) non-string-like objects. |
60 | 60 | """ |
| 61 | # Handle the common case first, saves 30-40% in performance when s |
| 62 | # is an instance of unicode. This function gets called often in that |
| 63 | # setting. |
| 64 | if isinstance(s, unicode): |
| 65 | return s |
61 | 66 | if strings_only and is_protected_type(s): |
62 | 67 | return s |
63 | 68 | try: |
diff --git a/django/utils/formats.py b/django/utils/formats.py
index 372998f..69c9fed 100644
a
|
b
|
from django.utils.importlib import import_module
|
7 | 7 | from django.utils.encoding import smart_str |
8 | 8 | from django.utils import dateformat, numberformat, datetime_safe |
9 | 9 | |
| 10 | # These constants are here so that we don't need to construct a new string |
| 11 | # every time x_format is called. |
| 12 | DECIMAL_SEPARATOR = 'DECIMAL_SEPARATOR' |
| 13 | NUMBER_GROUPING = 'NUMBER_GROUPING' |
| 14 | THOUSAND_SEPARATOR = 'THOUSAND_SEPARATOR' |
| 15 | DATE_FORMAT = 'DATE_FORMAT' |
| 16 | TIME_FORMAT = 'TIME_FORMAT' |
| 17 | DATETIME_FORMAT = 'DATETIME_FORMAT' |
| 18 | DATE_INPUT_FORMATS = 'DATE_INPUT_FORMATS' |
| 19 | TIME_INPUT_FORMATS = 'TIME_INPUT_FORMATS' |
| 20 | DATETIME_INPUT_FORMATS = 'DATETIME_INPUT_FORMATS' |
| 21 | |
| 22 | # format_cache is a mapping from (format_type, lang) to the format string. |
| 23 | # By using the cache, it is possible to avoid running get_format_modules |
| 24 | # repeatedly. |
| 25 | _format_cache = {} |
| 26 | |
10 | 27 | def get_format_modules(reverse=False): |
11 | 28 | """ |
12 | 29 | Returns an iterator over the format modules found in the project and Django |
13 | 30 | """ |
| 31 | lang = get_language() |
14 | 32 | modules = [] |
15 | | if not check_for_language(get_language()) or not settings.USE_L10N: |
| 33 | if not check_for_language(lang) or not settings.USE_L10N: |
16 | 34 | return modules |
17 | | locale = to_locale(get_language()) |
| 35 | locale = to_locale(lang) |
18 | 36 | if settings.FORMAT_MODULE_PATH: |
19 | 37 | format_locations = [settings.FORMAT_MODULE_PATH + '.%s'] |
20 | 38 | else: |
… |
… |
def get_format_modules(reverse=False):
|
34 | 52 | modules.reverse() |
35 | 53 | return modules |
36 | 54 | |
37 | | def get_format(format_type): |
| 55 | def get_format(format_type, lang=None): |
38 | 56 | """ |
39 | 57 | For a specific format type, returns the format for the current |
40 | 58 | language (locale), defaults to the format in the settings. |
41 | 59 | format_type is the name of the format, e.g. 'DATE_FORMAT' |
42 | 60 | """ |
43 | | format_type = smart_str(format_type) |
| 61 | global _format_cache |
44 | 62 | if settings.USE_L10N: |
45 | | for module in get_format_modules(): |
46 | | try: |
47 | | return getattr(module, format_type) |
48 | | except AttributeError: |
49 | | pass |
| 63 | if lang is None: |
| 64 | lang = get_language() |
| 65 | try: |
| 66 | return _format_cache[(format_type, lang)] \ |
| 67 | or getattr(settings, format_type) |
| 68 | except KeyError: |
| 69 | for module in get_format_modules(): |
| 70 | try: |
| 71 | val = getattr(module, format_type) |
| 72 | _format_cache[(format_type, lang)] = val |
| 73 | return val |
| 74 | except AttributeError: |
| 75 | pass |
| 76 | _format_cache[(format_type, lang)] = None |
50 | 77 | return getattr(settings, format_type) |
51 | 78 | |
52 | 79 | def date_format(value, format=None): |
… |
… |
def date_format(value, format=None):
|
54 | 81 | Formats a datetime.date or datetime.datetime object using a |
55 | 82 | localizable format |
56 | 83 | """ |
57 | | return dateformat.format(value, get_format(format or 'DATE_FORMAT')) |
| 84 | return dateformat.format(value, get_format(format or DATE_FORMAT)) |
58 | 85 | |
59 | 86 | def time_format(value, format=None): |
60 | 87 | """ |
61 | 88 | Formats a datetime.time object using a localizable format |
62 | 89 | """ |
63 | | return dateformat.time_format(value, get_format(format or 'TIME_FORMAT')) |
| 90 | return dateformat.time_format(value, get_format(format or TIME_FORMAT)) |
64 | 91 | |
65 | 92 | def number_format(value, decimal_pos=None): |
66 | 93 | """ |
67 | 94 | Formats a numeric value using localization settings |
68 | 95 | """ |
| 96 | lang = None |
| 97 | if settings.USE_I18N: |
| 98 | lang = get_language() |
69 | 99 | return numberformat.format( |
70 | 100 | value, |
71 | | get_format('DECIMAL_SEPARATOR'), |
| 101 | get_format(DECIMAL_SEPARATOR, lang), |
72 | 102 | decimal_pos, |
73 | | get_format('NUMBER_GROUPING'), |
74 | | get_format('THOUSAND_SEPARATOR'), |
| 103 | get_format(NUMBER_GROUPING, lang), |
| 104 | get_format(THOUSAND_SEPARATOR, lang), |
75 | 105 | ) |
76 | 106 | |
77 | 107 | def localize(value): |
… |
… |
def localize(value):
|
82 | 112 | if isinstance(value, (decimal.Decimal, float, int)): |
83 | 113 | return number_format(value) |
84 | 114 | elif isinstance(value, datetime.datetime): |
85 | | return date_format(value, 'DATETIME_FORMAT') |
| 115 | return date_format(value, DATETIME_FORMAT) |
86 | 116 | elif isinstance(value, datetime.date): |
87 | 117 | return date_format(value) |
88 | 118 | elif isinstance(value, datetime.time): |
89 | | return time_format(value, 'TIME_FORMAT') |
| 119 | return time_format(value, TIME_FORMAT) |
90 | 120 | else: |
91 | 121 | return value |
92 | 122 | |
… |
… |
def localize_input(value, default=None):
|
99 | 129 | return number_format(value) |
100 | 130 | if isinstance(value, datetime.datetime): |
101 | 131 | value = datetime_safe.new_datetime(value) |
102 | | format = smart_str(default or get_format('DATETIME_INPUT_FORMATS')[0]) |
| 132 | format = smart_str(default or get_format(DATETIME_INPUT_FORMATS)[0]) |
103 | 133 | return value.strftime(format) |
104 | 134 | elif isinstance(value, datetime.date): |
105 | 135 | value = datetime_safe.new_date(value) |
106 | | format = smart_str(default or get_format('DATE_INPUT_FORMATS')[0]) |
| 136 | format = smart_str(default or get_format(DATE_INPUT_FORMATS)[0]) |
107 | 137 | return value.strftime(format) |
108 | 138 | elif isinstance(value, datetime.time): |
109 | | format = smart_str(default or get_format('TIME_INPUT_FORMATS')[0]) |
| 139 | format = smart_str(default or get_format(TIME_INPUT_FORMATS)[0]) |
110 | 140 | return value.strftime(format) |
111 | 141 | return value |
112 | 142 | |
… |
… |
def sanitize_separators(value):
|
116 | 146 | thousand separator setting. Used with form field input. |
117 | 147 | """ |
118 | 148 | if settings.USE_L10N: |
119 | | decimal_separator = get_format('DECIMAL_SEPARATOR') |
| 149 | decimal_separator = get_format(DECIMAL_SEPARATOR) |
120 | 150 | if isinstance(value, basestring): |
121 | 151 | parts = [] |
122 | 152 | if decimal_separator in value: |
123 | 153 | value, decimals = value.split(decimal_separator, 1) |
124 | 154 | parts.append(decimals) |
125 | 155 | if settings.USE_THOUSAND_SEPARATOR: |
126 | | parts.append(value.replace(get_format('THOUSAND_SEPARATOR'), '')) |
| 156 | parts.append(value.replace(get_format(THOUSAND_SEPARATOR), '')) |
127 | 157 | else: |
128 | 158 | parts.append(value) |
129 | 159 | value = '.'.join(reversed(parts)) |
diff --git a/django/utils/numberformat.py b/django/utils/numberformat.py
index 129c27f..d6dbef8 100644
a
|
b
|
|
1 | 1 | from django.conf import settings |
| 2 | from django.utils.safestring import mark_safe |
| 3 | |
2 | 4 | |
3 | 5 | def format(number, decimal_sep, decimal_pos, grouping=0, thousand_sep=''): |
4 | 6 | """ |
… |
… |
def format(number, decimal_sep, decimal_pos, grouping=0, thousand_sep=''):
|
11 | 13 | * thousand_sep: Thousand separator symbol (for example ",") |
12 | 14 | |
13 | 15 | """ |
| 16 | use_grouping = settings.USE_L10N and settings.USE_THOUSAND_SEPARATOR \ |
| 17 | and grouping |
| 18 | # Make the common case fast: |
| 19 | if isinstance(number, int) and not use_grouping and not decimal_pos: |
| 20 | return mark_safe(unicode(number)) |
14 | 21 | # sign |
15 | 22 | if float(number) < 0: |
16 | 23 | sign = '-' |
17 | 24 | else: |
18 | 25 | sign = '' |
19 | | # decimal part |
20 | 26 | str_number = unicode(number) |
21 | 27 | if str_number[0] == '-': |
22 | 28 | str_number = str_number[1:] |
| 29 | # decimal part |
23 | 30 | if '.' in str_number: |
24 | 31 | int_part, dec_part = str_number.split('.') |
25 | 32 | if decimal_pos: |
… |
… |
def format(number, decimal_sep, decimal_pos, grouping=0, thousand_sep=''):
|
30 | 37 | dec_part = dec_part + ('0' * (decimal_pos - len(dec_part))) |
31 | 38 | if dec_part: dec_part = decimal_sep + dec_part |
32 | 39 | # grouping |
33 | | if settings.USE_L10N and settings.USE_THOUSAND_SEPARATOR and grouping: |
| 40 | if use_grouping: |
34 | 41 | int_part_gd = '' |
35 | 42 | for cnt, digit in enumerate(int_part[::-1]): |
36 | 43 | if cnt and not cnt % grouping: |
37 | 44 | int_part_gd += thousand_sep |
38 | 45 | int_part_gd += digit |
39 | 46 | int_part = int_part_gd[::-1] |
40 | | |
41 | 47 | return sign + int_part + dec_part |
42 | 48 | |