8000 bpo-36004: Add date.fromisocalendar by pganssle · Pull Request #11888 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-36004: Add date.fromisocalendar #11888

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

Merged
merged 14 commits into from
Apr 29, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Switch to new method of detecting ISO long years
This is equivalent but uses only existing helper functions and in many
cases will be slightly more efficient.
  • Loading branch information
pganssle committed Apr 29, 2019
commit 86edee5eda5acb9975a6c1b8d20322edab4cc24a
20 changes: 12 additions & 8 deletions Lib/datetime.py
_iso_long_year_helper(year - 1) == 3):
Original file line number Diff line number Diff line change
Expand Up @@ -891,9 +891,17 @@ def fromisocalendar(cls, year, week, day):
raise ValueError(f"Year is out of range: {year}")

if not 0 < week < 53:
if not (week == 53 and
_iso_long_year_helper(year) == 4 or
out_of_range = True

if week == 53:
# ISO years have 53 weeks in them on years starting with a
# Thursday and leap years starting on a Wednesday
first_weekday = _ymd2ord(year, 1, 1) % 7
if (first_weekday == 4 or (first_weekday == 3 and
_is_leap(year))):
out_of_range = False

if out_of_range:
raise ValueError(f"Invalid week: {week}")

if not 0 < day < 8:
Expand Down Expand Up @@ -2153,10 +2161,6 @@ def __reduce__(self):
datetime.resolution = timedelta(microseconds=1)


def _iso_long_year_helper(year):
return (year + (year // 4) - (year // 100) + (year // 400)) % 7


def _isoweek1monday(year):
# Helper to calculate the day number of the Monday starting week 1
# XXX This could be done more efficiently
Expand Down Expand Up @@ -2500,7 +2504,7 @@ def _name_from_offset(delta):
_format_time, _format_offset, _is_leap, _isoweek1monday, _math,
_ord2ymd, _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord,
_divide_and_round, _parse_isoformat_date, _parse_isoformat_time,
_parse_hh_mm_ss_ff, _iso_long_year_helper)
_parse_hh_mm_ss_ff)
# XXX Since import * above excludes names that start with _,
# docstring does not get overwritten. In the future, it may be
# appropriate to maintain a single module level docstring and
Expand Down
21 changes: 13 additions & 8 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3004,12 +3004,9 @@ date_fromisoformat(PyObject *cls, PyObject *dtstr)
}


static int _iso_long_year_helper(int year) {
return ((year + (year / 4) - (year / 100) + (year / 400)) % 7);
}

static PyObject *
date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw) {
date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw)
{
static char *keywords[] = {
"year", "week", "day", NULL
};
Expand All @@ -3033,9 +3030,17 @@ date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw) {
}

if (week <= 0 || week >= 53) {
if (!(week == 53 &&
(_iso_long_year_helper(year) == 4 ||
_iso_long_year_helper(year - 1) == 3))) {
int out_of_range = 1;
if (week == 53) {
// ISO years have 53 weeks in it on years starting with a Thursday
// and on leap years starting on Wednesday
int first_weekday = weekday(year, 1, 1);
if (first_weekday == 3 || (first_weekday == 2 && is_leap(year))) {
out_of_range = 0;
}
}

if (out_of_range) {
PyErr_Format(PyExc_ValueError, "Invalid week: %d", week);
return NULL;
}
Expand Down
0