Opened 8 years ago

Closed 6 years ago

# Add week numbers to calendar

Reported by: Owned by: anonymous Steffen Hoffmann normal WikiCalendarMacro normal week number calendar Ryan J Ollos, Jun Omae 0.11

### Description

Great macro :-)

It would be even grater if one could display week numbers in the calendar.

### comment:1 follow-up:  2 Changed 8 years ago by Steffen Hoffmann

Great macro :-)

Thank you.

It would be even grater if one could display week numbers in the calendar.

Uh, well. Certainly I'd have used this too, but hesitated to add such a feature after digging into the issue a bit, as there is no easy way, because there is NO universal definition worldwide. [1][2]

I'll leave this as a hint for further development, but without a patch to start on you'll most probably not see this happening soon, at least not this year, sorry.

### comment:2 in reply to:  1 Changed 6 years ago by Steffen Hoffmann

Component: WikiTicketCalendarMacro → WikiCalendarMacro

... hesitated to add such a feature after digging into the issue a bit, as there is no easy way, because there is NO universal definition worldwide.

Sure, but we could still attempt it at least and stick to an ISO standard as done for first-day-of week (#7639). And let's make this feature available to both wiki macros in the united code base too.

### comment:3 follow-up:  4 Changed 6 years ago by Steffen Hoffmann

Cc: Ryan J Ollos Jun Omae added; anonymous removed

My initial implementation was:

def _get_weeknumber(dt, week_start, locale=None):
if has_babel:
from babel.dates import format_date
return int(format_date(dt, 'w', locale=locale))
else:
if week_start == 6:
return int(dt.strftime('%U'))
return int(dt.strftime('%W'))


It took me about two working days to figure out, that neither Python core modules nor Babel do handle week numbering according to established common standards.

In fact, in weeks bridging years I see different week numbers assigned to days of the old year vs. days of the new year, effectively increasing the number of weeks to 53/54 instead of expected 52/53! Even in Babel calculation seems to unconditionally count from week with 1st of Jan as week 1 (the US definition) for any locale I tried.

So I've researched more and done an own calculation. I never dreamed, it could become that complicated again, after significant simplifications for the whole calendar build algorithm by introducing Babel lately (#10992).

I'll implement automatic switching between ISO (default) and US rule (if detecting first weekday at == Sunday), and allow for pinning individual calendar instances to on of three different numbering schemes, selected by an half-intuitive number:

1
week 1 is the week with Jan 01. (US)
4
week 1 is the week with Jan 04. (ISO)
7
week 1 is the week with Jan 07. Pakistan, maybe others

### comment:4 in reply to:  3 ; follow-up:  5 Changed 6 years ago by Jun Omae

Even in Babel calculation seems to unconditionally count from week with 1st of Jan as week 1 (the US definition) for any locale I tried.

In Babel, the week of year depends on locale with territory.

>>> from babel.dates import format_date
>>> from datetime import date
>>> format_date(date(2006, 1, 1), format='w', locale='en_US')
u'1'
>>> format_date(date(2006, 1, 1), format='w', locale='de')
u'1'
>>> format_date(date(2006, 1, 1), format='w', locale='de_DE')
u'52'


But, in Trac, the locales except some locales have no territory attribute. In the case, it can use babel.core.LOCALE_ALIASES to map lang to lang-territory (e.g. de to de_DE).

### comment:5 in reply to:  4 ; follow-ups:  8  11 Changed 6 years ago by Steffen Hoffmann

Even in Babel calculation seems to unconditionally count from week with 1st of Jan as week 1 (the US definition) for any locale I tried.

In Babel, the week of year depends on locale with territory.

Oh, I clearly missed that yet.

But, in Trac, the locales except some locales have no territory attribute. In the case, it can use babel.core.LOCALE_ALIASES to map lang to lang-territory (e.g. de to de_DE).

Now I've seen the work you've already done last year on the issue for Trac core. Nice, and thanks for the pointers.

What I still do not understand: Wouldn't it be sensible to at least try to rather take the territory from the complete req.language listing than let Babel guess it from possibly truncated language setting in Trac right-away?

### comment:6 follow-up:  9 Changed 6 years ago by Steffen Hoffmann

But go only one or two years further on to see, that calculation is wrong even with locale including territory information:

>>> date(2008, 12, 31).weekday()
2
>>> date(2009, 1, 1).weekday()
3
>>> format_date(date(2008, 12, 31), format='w', locale='de_DE')
u'53'
>>> format_date(date(2009, 1, 1), format='w', locale='de_DE')
u'1'


The week number changes between Tuesday and Wednesday. It shouldn't, right? As long as you look on the first day of the week and display that week number, you won't see the difference. But it is obviously there.

### comment:7 Changed 6 years ago by Steffen Hoffmann

Using Babel's format_date:

 Trac[macros] DEBUG: Locale setting for wiki calendar: German (Germany)
Trac[macros] DEBUG: CALENDAR from 29.12.2008 to 01.02.2009
Trac[macros] DEBUG: Day 29.12.2008 in week 53
Trac[macros] DEBUG: Day 30.12.2008 in week 53
Trac[macros] DEBUG: Day 31.12.2008 in week 53
Trac[macros] DEBUG: Day 01.01.2009 in week 1
Trac[macros] DEBUG: Day 02.01.2009 in week 1
Trac[macros] DEBUG: Day 03.01.2009 in week 1
Trac[macros] DEBUG: Day 04.01.2009 in week 1
Trac[macros] DEBUG: Day 05.01.2009 in week 2


and using my standards-conform algo:

 Trac[macros] DEBUG: Locale setting for wiki calendar: German (Germany)
Trac[macros] DEBUG: CALENDAR from 29.12.2008 to 01.02.2009
Trac[macros] DEBUG: Day 29.12.2008 in week 1
Trac[macros] DEBUG: Day 30.12.2008 in week 1
Trac[macros] DEBUG: Day 31.12.2008 in week 1
Trac[macros] DEBUG: Day 01.01.2009 in week 1
Trac[macros] DEBUG: Day 02.01.2009 in week 1
Trac[macros] DEBUG: Day 03.01.2009 in week 1
Trac[macros] DEBUG: Day 04.01.2009 in week 1
Trac[macros] DEBUG: Day 05.01.2009 in week 2


### comment:8 in reply to:  5 Changed 6 years ago by Steffen Hoffmann

But, in Trac, the locales except some locales have no territory attribute. In the case, it can use babel.core.LOCALE_ALIASES to map lang to lang-territory (e.g. de to de_DE).

Now I've seen the work you've already done last year on the issue for Trac core. Nice, and thanks for the pointers.

What I still do not understand: Wouldn't it be sensible to at least try to rather take the territory from the complete req.language listing than let Babel guess it from possibly truncated language setting in Trac right-away?

This one from inside expand_macro is not fully tested yet, especially not with Trac down to 0.11, but as you'll see, I did already care for things like non-existent attributes (if someone uses Babel + Trac-0.11 combined).

        # Respect user's locale, if available.
try:
loc_req = str(formatter.req.locale)
except AttributeError:
# Available since Trac 0.12.
loc_req = None
loc = None
if has_babel:
if loc_req:
try:
loc = Locale.parse(loc_req)
except UnknownLocaleError:
pass
if loc and not loc.territory:
try:
for loc_req in formatter.req.languages:
loc = Locale.parse(loc_req.replace('-', '_'))
break # first one rules
except (AttributeError, UnknownLocaleError):
pass
if not loc:
# Try system default.
loc = Locale.default('LC_TIME')
if loc and not loc.territory and loc.language in LOCALE_ALIASES:
loc = Locale.parse(LOCALE_ALIASES[loc.language])
if not loc:
# Default fallback.
loc = Locale('en', 'US')
env.log.debug('Locale setting for wiki calendar: %s'
% loc.get_display_name('en'))


I try to get the missing territory info from the first of browser's preferred languages, and only after that fails I do resort to guessing it with Babel as suggested.

### Changed 6 years ago by Steffen Hoffmann

wrong week numbers because of two week numbers for 1 week

### comment:9 in reply to:  6 ; follow-up:  10 Changed 6 years ago by Steffen Hoffmann

The week number changes between Tuesday and Wednesday. It shouldn't, right? As long as you look on the first day of the week and display that week number, you won't see the difference.

Not true, you see it, because the next week after the 'mixed' on is (correctly) week 2:

Ultimately, 29-Dec-2009 needs to get week number 1 assigned for German locale settings.

### comment:10 in reply to:  9 Changed 6 years ago by Jun Omae

Ultimately, 29-Dec-2009 needs to get week number 1 assigned for German locale settings.

Hmmm, it seems that Babel has the issues about week number....

And so, I found the workaround. Retrieving week number, use last day in the week instead of first day. See test-weeknum.py.

>>> from babel.dates import format_date
>>> from datetime import date
>>> format_date(date(2008, 12, 29), format="yyyy-MM-dd YYYY'W'ww", locale='de_DE')
u'2008-12-29 2008W53'
>>> format_date(date(2009, 1, 4), format="yyyy-MM-dd YYYY'W'ww", locale='de_DE')
u'2009-01-04 2009W01'

\$ python2.4 ./test-weeknum.py 2006 2009 de_DE
| Mo. Di. Mi. Do. Fr. Sa. So.
2006W52 | 25  26  27  28  29  30  31
2007W01 |  1   2   3   4   5   6   7

| Mo. Di. Mi. Do. Fr. Sa. So.
2008W01 | 31   1   2   3   4   5   6
2008W02 |  7   8   9  10  11  12  13

| Mo. Di. Mi. Do. Fr. Sa. So.
2009W01 | 29  30  31   1   2   3   4
2009W02 |  5   6   7   8   9  10  11

| Mo. Di. Mi. Do. Fr. Sa. So.
2009W53 | 28  29  30  31   1   2   3
2010W01 |  4   5   6   7   8   9  10


### comment:11 in reply to:  5 ; follow-up:  12 Changed 6 years ago by Jun Omae

What I still do not understand: Wouldn't it be sensible to at least try to rather take the territory from the complete req.language listing than let Babel guess it from possibly truncated language setting in Trac right-away?

Oh, that makes sense. However, AFAIK, most browsers send Accept-Language header without country code if not English (e.g. en-US, en-GB) nor Chinese (e.g. zh-CN, zh-TW).

Example in Chrome with Japanese settings:

Accept-Language:ja,en-US;q=0.8,en;q=0.6


### comment:12 in reply to:  11 ; follow-up:  13 Changed 6 years ago by Steffen Hoffmann

What I still do not understand: Wouldn't it be sensible to at least try to rather take the territory from the complete req.language listing than let Babel guess it from possibly truncated language setting in Trac right-away?

Oh, that makes sense. However, AFAIK, most browsers send Accept-Language header without country code if not English (e.g. en-US, en-GB) nor Chinese (e.g. zh-CN, zh-TW).

Hm, it may depend on browser brand and more. I'm testing with FF3@Debian with 6 or more languages in settings, and they all make it through to req.languages (de-de followed by de, en-us, us, ru, ja), so my proposed logic works great. While we're discussing, maybe I should propose it for inclusion in Trac core too? And file a ticket against Babel? I'll do this at least after resolving my issue with this plugin.

Btw, great to have the discussion here. I see, how developers in very different locations and with different view points get further than same number would do in one place. Thank you.

### comment:13 in reply to:  12 ; follow-up:  15 Changed 6 years ago by Jun Omae

While we're discussing, maybe I should propose it for inclusion in Trac core too? And file a ticket against Babel? I'll do this at least after resolving my issue with this plugin.

Sure. After trac:r11776, Trac now searches in req.languages for "first week day" if the locale has no territory. Thanks again, Steffen!

### comment:14 Changed 6 years ago by Steffen Hoffmann

(In [12989]) WikiCalendarMacro: Add optional week numbers, refs #1145, #7639 and #8175.

Rationale and constraints of current implementation:

• support any calendar per instance (use 'w' key-word) - no dependencies
• use basic start-of-week negotiation, if Babel is not installed
• use auto-negotiation for locale-aware Trac versions (since Trac 0.12)
• use advanced locale detection (similar to Trac 1.0.2)

Because I've found an issue with week number calculation in Babel, this plugin does it on its own for now.

### comment:15 in reply to:  13 Changed 6 years ago by Steffen Hoffmann

While we're discussing, maybe I should propose it for inclusion in Trac core too? ...

Sure. After trac:r11776, Trac now searches in req.languages for "first week day" if the locale has no territory. Thanks again, Steffen!

I've been lucky to re-use some of your code improvements in turn as well. Thank you too.

### comment:16 Changed 6 years ago by Steffen Hoffmann

Resolution: → fixed new → closed

(In [12991]) WikiCalendarMacro: Releasing current, tested macro package as final product, closes #7639, #8175, #9718, #10991, #10992 and #10993.

Special thanks to Jun Omae for pushing development by testing and providing valuable hints in our discussion about utilizing Babel for better localization and for making macro execution thread-safe as well.

### Modify Ticket

Change Properties