Skip to content

get_period_id() incorrectly handles day period rule crossing 0:00 since Babel 2.4.0 #870

Closed
@jun66j5

Description

@jun66j5

Overview Description

According to https://github.com/unicode-org/cldr/blob/release-41/common/supplemental/dayPeriods.xml#L15-L22, there is dayPeriodRule crossing 0:00 for en locale.

<dayPeriodRules locales="en">
        ...
        <dayPeriodRule type="night1" from="21:00" before="06:00"/>      <!-- night -->
</dayPeriodRules>

I noticed get_period_id() incorrectly handles this day period rule.

>>> dates.get_period_id(time(23), locale=en_US)
'pm'  # => should be 'night1'
>>> dates.get_period_id(time(1), locale=en_US)
'am'  # => should be 'night1'

Steps to Reproduce

>>> from datetime import time
>>> from babel import Locale, dates
>>> en_US = Locale.parse('en_US')
>>> dates.get_period_id(time(23), locale=en_US)
'pm'  # => should be 'night1'
>>> dates.get_period_id(time(1), locale=en_US)
'am'  # => should be 'night1'
>>> en_US = Locale.parse('en_US')
>>> for h in range(24):
...   t = time(h)
...   print(t, dates.get_period_id(t, locale=en_US))
...
00:00:00 midnight
01:00:00 am
02:00:00 am
03:00:00 am
04:00:00 am
05:00:00 am
06:00:00 morning1
07:00:00 morning1
08:00:00 morning1
09:00:00 morning1
10:00:00 morning1
11:00:00 morning1
12:00:00 noon
13:00:00 afternoon1
14:00:00 afternoon1
15:00:00 afternoon1
16:00:00 afternoon1
17:00:00 afternoon1
18:00:00 evening1
19:00:00 evening1
20:00:00 evening1
21:00:00 pm
22:00:00 pm
23:00:00 pm

Actual Results

>>> dates.get_period_id(time(23), locale=en_US)
'pm'
>>> dates.get_period_id(time(1), locale=en_US)
'am''

Expected Results

dates.get_period_id(time(23), locale=en_US) and dates.get_period_id(time(1), locale=en_US) should return 'night1'.

Also, we should add unit tests for get_period_id().

Reproducibility

The issue occurs with Babel 2.4.0 and later, however doesn't with 2.3.0 - 2.3.4.

Additional Information

It seems to be caused by changes of day period rule between Babel 2.3.4 (CLDR 28) and 2.4.0 (CLDR 29).

See also 8th list in https://unicode.org/reports/tr35/tr35-dates.html#4512-variable-periods

>>> import babel
>>> babel.__version__
'2.3.4'
>>> en_US = babel.Locale.parse('en_US')
>>> for _ in en_US.day_period_rules.get(None, {}).items(): _
...
('noon', [{'at': 43200}])
('morning1', [{'from': 21600, 'before': 43200}])
('afternoon1', [{'after': 43200, 'before': 64800}])
('night1', [{'after': 0, 'before': 21600}, {'from': 75600, 'before': 86400}])
('evening1', [{'from': 64800, 'before': 75600}])
('midnight', [{'at': 0}])
>>> import babel
>>> babel.__version__
'2.4.0'
>>> en_US = babel.Locale.parse('en_US')
>>> for _ in en_US.day_period_rules.get(None, {}).items(): _
...
('midnight', [{'at': 0}])
('noon', [{'at': 43200}])
('morning1', [{'before': 43200, 'from': 21600}])
('afternoon1', [{'before': 64800, 'from': 43200}])
('evening1', [{'before': 75600, 'from': 64800}])
('night1', [{'before': 21600, 'from': 75600}])

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions