FObersteiner
FObersteiner

Reputation: 25564

Inconsistency when parsing year-weeknum string to date

When parsing year-weeknum strings, I came across an inconsistency when comparing the results from %W and %U (docs):

What works:

from datetime import datetime

print("\nISO:") # for reference...
for i in range(1,8): # %u is 1-based
    print(datetime.strptime(f"2019-01-{i}", "%G-%V-%u"))
# ISO:
# 2018-12-31 00:00:00
# 2019-01-01 00:00:00
# 2019-01-02 00:00:00
# ...  
    
# %U -> week start = Sun
# first Sunday 2019 was 2019-01-06
print("\n %U:")    
for i in range(0,7):
    print(datetime.strptime(f"2019-01-{i}", "%Y-%U-%w"))
#  %U:
# 2019-01-06 00:00:00
# 2019-01-07 00:00:00
# 2019-01-08 00:00:00
# ...  

What is unexpected:

# %W -> week start = Mon
# first Monday 2019 was 2019-01-07
print("\n %W:")    
for i in range(0,7):
    print(datetime.strptime(f"2019-01-{i}", "%Y-%W-%w"))
#  %W:
# 2019-01-13 00:00:00 ## <-- ?! expected 2019-01-06
# 2019-01-07 00:00:00 
# 2019-01-08 00:00:00
# 2019-01-09 00:00:00
# 2019-01-10 00:00:00
# 2019-01-11 00:00:00
# 2019-01-12 00:00:00

The date jumping from 2019-01-13 to 2019-01-07? What's going on here? I don't see any ambiguities in the calendar for 2019... I also tried to parse the same dates in rust with chrono, and it fails for the %W directive -> playground example. A jump backwards in Python and an error in Rust, what am I missing here?

Upvotes: 3

Views: 64

Answers (2)

Kelly Bundy
Kelly Bundy

Reputation: 27599

That week goes from Monday January 7 to Sunday January 13.

%w is documented as "Weekday as a decimal number, where 0 is Sunday and 6 is Saturday.". So 0 means Sunday (= January 13), and 1 means Monday (= January 7).

Upvotes: 3

KaO
KaO

Reputation: 345

In your code, you're trying to parse the string "2019-01-0" as a day of a year, which is not a valid day. That's why you're encountering an unexpected result when using the %W format code.

If you want to parse a date, you should specify a value that is bigger then 1 not 0.

Also keep it might help to keep the style consistent with f-string

f'(2019-01-{i:02d}')

which will add the leading 0 when necessary like the following.

2019-01-00
2019-01-01
2019-01-02
2019-01-03
2019-01-04
2019-01-05
2019-01-06

Here is your modified code:

for i in range(0,7):
    print(datetime.strptime(f"2019-01-{i}", "%Y-%W-%w"))

Upvotes: -2

Related Questions