Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dates formatting Y, w and W symbols for week-numbering #1179

Merged
merged 5 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 26 additions & 23 deletions babel/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,11 @@ def format_era(self, char: str, num: int) -> str:
def format_year(self, char: str, num: int) -> str:
value = self.value.year
if char.isupper():
value = self.value.isocalendar()[0]
month = self.value.month
if month == 1 and self.value.day < 7 and self.get_week_of_year() >= 52:
value -= 1
elif month == 12 and self.value.day > 25 and self.get_week_of_year() <= 2:
value += 1
year = self.format(value, num)
if num == 2:
year = year[-2:]
Expand All @@ -1505,18 +1509,10 @@ def format_month(self, char: str, num: int) -> str:

def format_week(self, char: str, num: int) -> str:
if char.islower(): # week of year
day_of_year = self.get_day_of_year()
week = self.get_week_number(day_of_year)
if week == 0:
date = self.value - datetime.timedelta(days=day_of_year)
week = self.get_week_number(self.get_day_of_year(date),
date.weekday())
week = self.get_week_of_year()
return self.format(week, num)
else: # week of month
week = self.get_week_number(self.value.day)
if week == 0:
date = self.value - datetime.timedelta(days=self.value.day)
week = self.get_week_number(date.day, date.weekday())
week = self.get_week_of_month()
return str(week)

def format_weekday(self, char: str = 'E', num: int = 4) -> str:
Expand Down Expand Up @@ -1677,6 +1673,25 @@ def get_day_of_year(self, date: datetime.date | None = None) -> int:
date = self.value
return (date - date.replace(month=1, day=1)).days + 1

def get_week_of_year(self) -> int:
"""Return the week of the year."""
day_of_year = self.get_day_of_year(self.value)
week = self.get_week_number(day_of_year)
if week == 0:
date = datetime.date(self.value.year - 1, 12, 31)
week = self.get_week_number(self.get_day_of_year(date),
date.weekday())
elif week > 52:
weekday = datetime.date(self.value.year + 1, 1, 1).weekday()
if self.get_week_number(1, weekday) == 1 and \
32 - (weekday - self.locale.first_week_day) % 7 <= self.value.day:
week = 1
return week

def get_week_of_month(self) -> int:
"""Return the week of the month."""
return self.get_week_number(self.value.day)

def get_week_number(self, day_of_period: int, day_of_week: int | None = None) -> int:
"""Return the number of the week of a day within a period. This may be
the week number in a year or the week number in a month.
Expand All @@ -1703,20 +1718,8 @@ def get_week_number(self, day_of_period: int, day_of_week: int | None = None) ->
if first_day < 0:
first_day += 7
week_number = (day_of_period + first_day - 1) // 7

if 7 - first_day >= self.locale.min_week_days:
week_number += 1

if self.locale.first_week_day == 0:
# Correct the weeknumber in case of iso-calendar usage (first_week_day=0).
# If the weeknumber exceeds the maximum number of weeks for the given year
# we must count from zero.For example the above calculation gives week 53
# for 2018-12-31. By iso-calender definition 2018 has a max of 52
# weeks, thus the weeknumber must be 53-52=1.
max_weeks = datetime.date(year=self.value.year, day=28, month=12).isocalendar()[1]
if week_number > max_weeks:
week_number -= max_weeks

return week_number


Expand Down
Loading
Loading