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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISOWeek, ISOWeekDate and OrdinalDate #94

Open
FBruzzesi opened this issue Aug 28, 2023 · 1 comment
Open

ISOWeek, ISOWeekDate and OrdinalDate #94

FBruzzesi opened this issue Aug 28, 2023 · 1 comment

Comments

@FBruzzesi
Copy link

FBruzzesi commented Aug 28, 2023

Hi everyone 馃憢馃徏, I hope this is the right place to ask 馃檭

Lately I have been working a lot with ISO Week, ISO Week Date and Ordinal Dates formats (resp. YYYY-WNN, YYYY-WNN-D, YYYY-DDD, where YYYY indicates the year, NN the week number, D the weekday, DDD the day of the year, and W is just a literal)

In terms of pydantic types, these would just be pattern constrained strings (*), however it could be useful to have them already implemented to plug and play:

(Pseudo)implementation:

from typing import Annotated, Final
from pydantic import BaseModel, StringConstraints

# Year should range between 0001 and 9999
YEAR_MATCH: Final[str] = r"([1-9]\d{3}|0\d{2}[1-9]|0\d[1-9]\d|0[1-9]\d{2})"

# Week should range between 01 and 53
WEEK_MATCH: Final[str] = r"(W0[1-9]|W[1-4]\d|W5[0-3])"

# Weekday should range between 1 and 7
WEEK_DAY_MATCH: Final[str] = r"([1-7])"

# Ordinal day should range between 001 and 366
ORDINAL_DAY_MATCH: Final[str] = r"(36[0-6]|3[0-5]\d|[1-2]\d{2}|0\d[1-9]|0\d[1-9])"

# Compose patterns
ISOWEEK_PATTERN: Final[str] = r"^{}-{}$".format(YEAR_MATCH, WEEK_MATCH)
ISOWEEKDATE_PATTERN: Final[str] = r"^{}-{}-{}$".format(YEAR_MATCH, WEEK_MATCH, WEEK_DAY_MATCH)
ORDINALDATE_PATTERN: Final[str] = r"^{}-{}$".format(YEAR_MATCH, ORDINAL_DAY_MATCH)

# Pydantic compatible types
ISOWeek = Annotated[str, StringConstraints(pattern=ISOWEEK_PATTERN)]
ISOWeekDate = Annotated[str, StringConstraints(pattern=ISOWEEKDATE_PATTERN)]
OrdinalDate = Annotated[str, StringConstraints(pattern=ORDINALDATE_PATTERN)]

(*) While this is not 100% correct because some combinations should not be possible (not every year has 53 weeks and/or 366 days), python datetime module deals with that automatically:

from datetime import datetime
# 2023 has 52 weeks
datetime.strptime("2023-W53-1", "%G-W%V-%u")  # datetime(2024, 1, 1, 0, 0)
datetime.strptime("2024-W01-1", "%G-W%V-%u")  # datetime(2024, 1, 1, 0, 0)

# 2023 has 365 days
datetime.strptime("2023-366", "%Y-%j")  # datetime(2024, 1, 1, 0, 0)
datetime.strptime("2024-001", "%Y-%j")  # datetime(2024, 1, 1, 0, 0)

Happy to open a PR if this is something you could be interested in adding

Edit: Each of these type could also have a compact version without dashes, i.e. matching the formats YYYYWNN, YYYYWNND and YYYYDDD, which implementation is straightforward from above.

Selected Assignee: @PrettyWood

@FBruzzesi
Copy link
Author

FBruzzesi commented Apr 29, 2024

Implemented in iso week and iso week date types in iso-week-date library.

I probably won't be adding ordinal support for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants