Skip to content

Commit

Permalink
Fix dates formatting Y, w and W symbols for week-numbering (#1179)
Browse files Browse the repository at this point in the history
  • Loading branch information
jun66j5 authored Jan 31, 2025
1 parent e9c3ef8 commit 363ad75
Show file tree
Hide file tree
Showing 2 changed files with 385 additions and 23 deletions.
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

0 comments on commit 363ad75

Please sign in to comment.